CINXE.COM

PEP 751 – A file format to record Python dependencies for installation reproducibility | peps.python.org

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 751 – A file format to record Python dependencies for installation reproducibility | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0751/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 751 – A file format to record Python dependencies for installation reproducibility | peps.python.org'> <meta property="og:description" content="This PEP proposes a new file format for specifying dependencies to enable reproducible installation in a Python environment. The format is designed to be human-readable and machine-generated. Installers consuming the file should be able to calculate wha..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0751/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This PEP proposes a new file format for specifying dependencies to enable reproducible installation in a Python environment. The format is designed to be human-readable and machine-generated. Installers consuming the file should be able to calculate wha..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li> <li><a href="../pep-0000/">PEP Index</a> &raquo; </li> <li>PEP 751</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 751 – A file format to record Python dependencies for installation reproducibility</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Brett Cannon &lt;brett&#32;&#97;t&#32;python.org&gt;</dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Proposal under active discussion and revision">Draft</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Topic<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="../topic/packaging/">Packaging</a></dd> <dt class="field-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">24-Jul-2024</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/59173" title="Discourse thread">25-Jul-2024</a> <a class="reference external" href="https://discuss.python.org/t/69721" title="Discourse thread">30-Oct-2024</a> <a class="reference external" href="https://discuss.python.org/t/77293" title="Discourse thread">15-Jan-2025</a></dd> <dt class="field-odd">Replaces<span class="colon">:</span></dt> <dd class="field-odd"><a class="reference external" href="../pep-0665/">665</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#file-name">File Name</a></li> <li><a class="reference internal" href="#file-format">File Format</a><ul> <li><a class="reference internal" href="#lock-version"><code class="docutils literal notranslate"><span class="pre">lock-version</span></code></a></li> <li><a class="reference internal" href="#environments"><code class="docutils literal notranslate"><span class="pre">environments</span></code></a></li> <li><a class="reference internal" href="#requires-python"><code class="docutils literal notranslate"><span class="pre">requires-python</span></code></a></li> <li><a class="reference internal" href="#created-by"><code class="docutils literal notranslate"><span class="pre">created-by</span></code></a></li> <li><a class="reference internal" href="#packages"><code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code></a><ul> <li><a class="reference internal" href="#packages-name"><code class="docutils literal notranslate"><span class="pre">packages.name</span></code></a></li> <li><a class="reference internal" href="#packages-version"><code class="docutils literal notranslate"><span class="pre">packages.version</span></code></a></li> <li><a class="reference internal" href="#packages-marker"><code class="docutils literal notranslate"><span class="pre">packages.marker</span></code></a></li> <li><a class="reference internal" href="#packages-requires-python"><code class="docutils literal notranslate"><span class="pre">packages.requires-python</span></code></a></li> <li><a class="reference internal" href="#packages-dependencies"><code class="docutils literal notranslate"><span class="pre">[[packages.dependencies]]</span></code></a></li> <li><a class="reference internal" href="#packages-direct"><code class="docutils literal notranslate"><span class="pre">packages.direct</span></code></a></li> <li><a class="reference internal" href="#packages-vcs"><code class="docutils literal notranslate"><span class="pre">[packages.vcs]</span></code></a><ul> <li><a class="reference internal" href="#packages-vcs-type"><code class="docutils literal notranslate"><span class="pre">packages.vcs.type</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-url"><code class="docutils literal notranslate"><span class="pre">packages.vcs.url</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-path"><code class="docutils literal notranslate"><span class="pre">packages.vcs.path</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-requested-revision"><code class="docutils literal notranslate"><span class="pre">packages.vcs.requested-revision</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-commit-id"><code class="docutils literal notranslate"><span class="pre">packages.vcs.commit-id</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.vcs.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-directory"><code class="docutils literal notranslate"><span class="pre">[packages.directory]</span></code></a><ul> <li><a class="reference internal" href="#packages-directory-path"><code class="docutils literal notranslate"><span class="pre">packages.directory.path</span></code></a></li> <li><a class="reference internal" href="#packages-directory-editable"><code class="docutils literal notranslate"><span class="pre">packages.directory.editable</span></code></a></li> <li><a class="reference internal" href="#packages-directory-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.directory.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-archive"><code class="docutils literal notranslate"><span class="pre">[packages.archive]</span></code></a><ul> <li><a class="reference internal" href="#packages-archive-url"><code class="docutils literal notranslate"><span class="pre">packages.archive.url</span></code></a></li> <li><a class="reference internal" href="#packages-archive-path"><code class="docutils literal notranslate"><span class="pre">packages.archive.path</span></code></a></li> <li><a class="reference internal" href="#packages-archive-size"><code class="docutils literal notranslate"><span class="pre">packages.archive.size</span></code></a></li> <li><a class="reference internal" href="#packages-archive-hashes"><code class="docutils literal notranslate"><span class="pre">[packages.archive.hashes]</span></code></a></li> <li><a class="reference internal" href="#packages-archive-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.archive.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-index"><code class="docutils literal notranslate"><span class="pre">packages.index</span></code></a></li> <li><a class="reference internal" href="#packages-sdist"><code class="docutils literal notranslate"><span class="pre">[packages.sdist]</span></code></a><ul> <li><a class="reference internal" href="#packages-sdist-name"><code class="docutils literal notranslate"><span class="pre">packages.sdist.name</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-upload-time"><code class="docutils literal notranslate"><span class="pre">packages.sdist.upload-time</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-url"><code class="docutils literal notranslate"><span class="pre">packages.sdist.url</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-path"><code class="docutils literal notranslate"><span class="pre">packages.sdist.path</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-size"><code class="docutils literal notranslate"><span class="pre">packages.sdist.size</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-hashes"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hashes</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-wheels"><code class="docutils literal notranslate"><span class="pre">[[packages.wheels]]</span></code></a><ul> <li><a class="reference internal" href="#packages-wheels-name"><code class="docutils literal notranslate"><span class="pre">packages.wheels.name</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-upload-time"><code class="docutils literal notranslate"><span class="pre">packages.wheels.upload-time</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-url"><code class="docutils literal notranslate"><span class="pre">packages.wheels.url</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-path"><code class="docutils literal notranslate"><span class="pre">packages.wheels.path</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-size"><code class="docutils literal notranslate"><span class="pre">packages.wheels.size</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-hashes"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hashes</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-attestation-identities"><code class="docutils literal notranslate"><span class="pre">[[packages.attestation-identities]]</span></code></a><ul> <li><a class="reference internal" href="#packages-attestation-identites-kind"><code class="docutils literal notranslate"><span class="pre">packages.attestation-identites.kind</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-tool"><code class="docutils literal notranslate"><span class="pre">[packages.tool]</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#tool"><code class="docutils literal notranslate"><span class="pre">[tool]</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#example">Example</a></li> <li><a class="reference internal" href="#installation">Installation</a></li> <li><a class="reference internal" href="#semantic-differences-with-requirements-txt-files">Semantic differences with <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code> files</a></li> </ul> </li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#recording-the-dependency-graph-for-installation-purposes">Recording the dependency graph for installation purposes</a></li> <li><a class="reference internal" href="#specifying-a-new-core-metadata-version-that-requires-consistent-metadata-across-files">Specifying a new core metadata version that requires consistent metadata across files</a></li> <li><a class="reference internal" href="#have-the-installer-do-dependency-resolution">Have the installer do dependency resolution</a></li> <li><a class="reference internal" href="#requiring-minimum-hash-algorithm-support">Requiring minimum hash algorithm support</a></li> <li><a class="reference internal" href="#file-naming">File naming</a><ul> <li><a class="reference internal" href="#using-pylock-toml-as-the-file-name">Using <code class="docutils literal notranslate"><span class="pre">*.pylock.toml</span></code> as the file name</a></li> <li><a class="reference internal" href="#using-pylock-as-the-file-name">Using <code class="docutils literal notranslate"><span class="pre">*.pylock</span></code> as the file name</a></li> <li><a class="reference internal" href="#not-having-a-naming-convention-for-the-file">Not having a naming convention for the file</a></li> </ul> </li> <li><a class="reference internal" href="#id1">File format</a><ul> <li><a class="reference internal" href="#use-json-over-toml">Use JSON over TOML</a></li> <li><a class="reference internal" href="#use-yaml-over-toml">Use YAML over TOML</a></li> </ul> </li> <li><a class="reference internal" href="#other-keys">Other keys</a><ul> <li><a class="reference internal" href="#a-single-hash-algorithm-for-the-whole-file">A single hash algorithm for the whole file</a></li> <li><a class="reference internal" href="#hashing-the-contents-of-the-lock-file-itself">Hashing the contents of the lock file itself</a></li> <li><a class="reference internal" href="#recording-the-creation-date-of-the-lock-file">Recording the creation date of the lock file</a></li> <li><a class="reference internal" href="#recording-the-package-indexes-used-in-searching">Recording the package indexes used in searching</a></li> <li><a class="reference internal" href="#locking-build-requirements-for-sdists">Locking build requirements for sdists</a></li> <li><a class="reference internal" href="#recording-possible-extras-and-dependency-groups">Recording possible extras and dependency groups</a></li> </ul> </li> <li><a class="reference internal" href="#simplification">Simplification</a><ul> <li><a class="reference internal" href="#drop-recording-the-package-version">Drop recording the package version</a></li> <li><a class="reference internal" href="#drop-the-requirement-to-specify-the-location-of-an-sdist-and-or-wheels">Drop the requirement to specify the location of an sdist and/or wheels</a></li> <li><a class="reference internal" href="#drop-requiring-file-size-and-hashes">Drop requiring file size and hashes</a></li> <li><a class="reference internal" href="#drop-recording-the-sdist-file-name">Drop recording the sdist file name</a></li> <li><a class="reference internal" href="#make-packages-wheels-a-table">Make <code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code> a table</a></li> </ul> </li> <li><a class="reference internal" href="#self-referential">Self-Referential</a><ul> <li><a class="reference internal" href="#drop-the-tool-table">Drop the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table</a></li> <li><a class="reference internal" href="#list-the-requirement-inputs-for-the-file">List the requirement inputs for the file</a></li> </ul> </li> <li><a class="reference internal" href="#auditing">Auditing</a><ul> <li><a class="reference internal" href="#recording-dependents">Recording dependents</a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP proposes a new file format for specifying dependencies to enable reproducible installation in a Python environment. The format is designed to be human-readable and machine-generated. Installers consuming the file should be able to calculate what to install without the need for dependency resolution at install-time.</p> </section> <section id="motivation"> <h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2> <p>Currently, no standard exists to create an immutable record, such as a lock file, which specifies what direct and indirect dependencies should be installed into a virtual environment.</p> <p>Considering there are at least five well-known solutions to this problem in the community (<a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">freeze</span></code>, <a class="reference external" href="https://pypi.org/project/pip-tools/">pip-tools</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, and <a class="reference external" href="https://github.com/astral-sh/uv">uv</a>), there seems to be an appetite for lock files in general.</p> <p>Those tools also vary in what locking scenarios they support. For instance, <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">freeze</span></code> and pip-tools only generate lock files for the current environment while PDM, Poetry, and uv can/try to lock for multiple environments at once. There’s also concerns around the lack of secure defaults in the face of supply chain attacks (e.g. including hashes for files).</p> <p>The lack of a standard also has some drawbacks. For instance, any tooling that wants to work with lock files must choose which format to support, potentially leaving users unsupported (e.g. <a class="reference external" href="https://docs.github.com/en/code-security/dependabot">Dependabot</a> only supporting select tools, same for cloud providers who can do dependency installations on your behalf, etc.). It also impacts portability between tools, which causes vendor lock-in. By not having compatibility and interoperability it fractures tooling around lock files where both users and tools have to choose what lock file format to use upfront and making it costly to use/switch to other formats (e.g. tooling around auditing a lock file). Rallying around a single format removes this cost/barrier.</p> <p>The closest the community has to a standard are pip’s <a class="reference external" href="https://pip.pypa.io/en/stable/reference/requirements-file-format/">requirements files</a> which all the aforementioned tools either use directly as their file format or export to (i.e. <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code>). Unfortunately, the format is not a standard but is supported by convention. It’s also designed very much for pip’s needs, limiting its flexibility and ease of use (e.g. it’s a bespoke file format). Lastly, it is not secure by default (e.g. file hash support is entirely an opt-in feature, you have to tell pip to not look for other dependencies outside of what’s in the requirements file, etc.).</p> <div class="admonition note"> <p class="admonition-title">Note</p> <p>Much of the motivation from <a class="pep reference internal" href="../pep-0665/" title="PEP 665 – A file format to list Python dependencies for reproducibility of an application">PEP 665</a> also applies to this PEP.</p> </div> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>The file format proposed by this PEP is designed to be human-readable. This is so that the contents of the file can be audited by a human to make sure no undesired dependencies end up being included in the lock file.</p> <p>The file format is also designed to not require a resolver at install time. This greatly simplifies reasoning about what would be installed when consuming a lock file. It should also lead to faster installs which are much more frequent than creating a lock file.</p> <p>The data in the file should be consumable by tools not written in Python. This allows for e.g. cloud hosting providers to write their own tool to perform installations in their preferred programming language.</p> <p>The file format should promote good security defaults. As the format is not meant to be human-writable, this means having tools provide security-related details is reasonable and not a costly burden.</p> <p>The contents of a lock file should be able to replace the vast majority of uses of <a class="reference external" href="https://pip.pypa.io/en/stable/reference/requirements-file-format/">requirements files</a> when used as a lock file (e.g. what <a class="reference external" href="https://pypi.org/project/pip-tools/">pip-tools</a> and <code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">freeze</span></code> emit). This means the file format specified by this PEP can, at minimum, act as an export target for tools which have their own internal lock file format.</p> </section> <section id="specification"> <h2><a class="toc-backref" href="#specification" role="doc-backlink">Specification</a></h2> <section id="file-name"> <h3><a class="toc-backref" href="#file-name" role="doc-backlink">File Name</a></h3> <p>A lock file MUST be named <code class="file docutils literal notranslate"><span class="pre">pylock.toml</span></code> or match the regular expression <code class="docutils literal notranslate"><span class="pre">r&quot;^pylock\.([^.]+)\.toml$&quot;</span></code> if a name for the lock file is desired or if multiple lock files exist. The use of the <code class="docutils literal notranslate"><span class="pre">.toml</span></code> file extension is to make syntax highlighting in editors easier and to reinforce the fact that the file format is meant to be human-readable. The prefix and suffix of a named file MUST be lowercase when possible, for easy detection and removal, e.g.:</p> <div class="highlight-Python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">11</span> <span class="ow">and</span> <span class="n">filename</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;pylock.&quot;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">filename</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">&quot;.toml&quot;</span><span class="p">):</span> <span class="n">name</span> <span class="o">=</span> <span class="n">filename</span><span class="o">.</span><span class="n">removeprefix</span><span class="p">(</span><span class="s2">&quot;pylock.&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">removesuffix</span><span class="p">(</span><span class="s2">&quot;.toml&quot;</span><span class="p">)</span> </pre></div> </div> <p>The expectation is that services that install lock files automatically will search for a lock file with the service’s name, then fallback to the generic <code class="docutils literal notranslate"><span class="pre">pylock.toml</span></code> (e.g. a cloud host service named Spam would first look for <code class="docutils literal notranslate"><span class="pre">pylock.spam.toml</span></code> to install, and if that file didn’t exist then install from <code class="docutils literal notranslate"><span class="pre">pylock.toml</span></code>).</p> <p>The lock file(s) SHOULD be located in the directory as appropriate for the scope of the lock file. Locking against a single <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>, for instance, would place the <code class="docutils literal notranslate"><span class="pre">pylock.toml</span></code> in the same directory. If the lock file covered multiple projects in a monorepo, then the expectation is the <code class="docutils literal notranslate"><span class="pre">pylock.toml</span></code> file would be in the directory that held all the projects being locked.</p> </section> <section id="file-format"> <h3><a class="toc-backref" href="#file-format" role="doc-backlink">File Format</a></h3> <p>The format of the file is <a class="reference external" href="https://toml.io/">TOML</a>.</p> <p>Tools SHOULD write their lock files in a consistent way to minimize noise in diff output. Keys in tables – including the top-level table – SHOULD be recorded in a consistent order (if inspiration is desired, this PEP has tried to write down keys in a logical order). As well, tools SHOULD sort arrays in consistent order. Usage of inline tables SHOULD also be kept consistent.</p> <section id="lock-version"> <h4><a class="toc-backref" href="#lock-version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">lock-version</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: string; value of <code class="docutils literal notranslate"><span class="pre">&quot;1.0&quot;</span></code></li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-metadata-version" title="(in Python Packaging User Guide)"><span>Metadata-Version</span></a></li> <li>Record the file format version that the file adheres to.</li> <li>This PEP specifies the initial version – and only valid value until future updates to the standard change it – as <code class="docutils literal notranslate"><span class="pre">&quot;1.0&quot;</span></code>.</li> <li>If a tool supports the major version but not the minor version, a tool SHOULD warn when an unknown key is seen.</li> <li>If an tool doesn’t support a major version, it MUST raise an error.</li> </ul> </section> <section id="environments"> <h4><a class="toc-backref" href="#environments" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">environments</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: Array of strings</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>A list of <a class="reference external" href="https://packaging.python.org/en/latest/specifications/dependency-specifiers/#dependency-specifiers-environment-markers" title="(in Python Packaging User Guide)"><span>Environment Markers</span></a> for which the lock file is considered compatible with.</li> <li>Tools SHOULD write exclusive/non-overlapping environment markers to ease in understanding.</li> </ul> </section> <section id="requires-python"> <h4><a class="toc-backref" href="#requires-python" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">requires-python</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>Specifies the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-requires-python" title="(in Python Packaging User Guide)"><span>Requires-Python</span></a> for the minimum Python version compatible for any environment supported by the lock file (i.e. the minimum viable Python version for the lock file).</li> </ul> </section> <section id="created-by"> <h4><a class="toc-backref" href="#created-by" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">created-by</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: Tools with their name in their lock file name</li> <li>Records the name of the tool used to create the lock file.</li> <li>Tools MAY use the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table to record enough details that it can be inferred what inputs were used to create the lock file.</li> <li>Tools SHOULD record the normalized name of the tool if it is available as a Python package to facilitate finding the tool.</li> </ul> </section> <section id="packages"> <h4><a class="toc-backref" href="#packages" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: array of tables</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>An array containing all packages that <em>may</em> be installed.</li> <li>Packages MAY be listed multiple times with varying data, but all packages to be installed MUST narrow down to a single entry at install time.</li> </ul> <section id="packages-name"> <h5><a class="toc-backref" href="#packages-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.name</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-name" title="(in Python Packaging User Guide)"><span>Name</span></a></li> <li>The name of the package <a class="reference external" href="https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization" title="(in Python Packaging User Guide)"><span class="xref std std-ref">normalized</span></a>.</li> </ul> </section> <section id="packages-version"> <h5><a class="toc-backref" href="#packages-version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.version</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-version" title="(in Python Packaging User Guide)"><span>Version</span></a></li> <li>The version of the package.</li> <li>The version SHOULD be specified when the version is known to be stable (i.e. when an <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format" title="(in Python Packaging User Guide)"><span class="xref std std-ref">sdist</span></a> or <a class="reference external" href="https://packaging.python.org/en/latest/specifications/binary-distribution-format/#binary-distribution-format" title="(in Python Packaging User Guide)"><span class="xref std std-ref">wheels</span></a> are specified).</li> <li>The version MUST NOT be included when it cannot be guaranteed to be consistent with the code used (i.e. when a <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-source-tree" title="(in Python Packaging User Guide)"><span class="xref std std-ref">source tree</span></a> is used).</li> </ul> </section> <section id="packages-marker"> <h5><a class="toc-backref" href="#packages-marker" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.marker</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a></li> <li>The <a class="reference external" href="https://packaging.python.org/en/latest/specifications/dependency-specifiers/#dependency-specifiers-environment-markers" title="(in Python Packaging User Guide)"><span class="xref std std-ref">environment marker</span></a> which specify when the package should be installed.</li> </ul> </section> <section id="packages-requires-python"> <h5><a class="toc-backref" href="#packages-requires-python" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.requires-python</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-requires-python" title="(in Python Packaging User Guide)"><span>Requires-Python</span></a></li> <li>Holds the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers" title="(in Python Packaging User Guide)"><span>Version specifiers</span></a> for Python version compatibility for the package.</li> </ul> </section> <section id="packages-dependencies"> <h5><a class="toc-backref" href="#packages-dependencies" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[[packages.dependencies]]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: array of tables</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>Records the other entries in <code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code> which are direct dependencies of this package.</li> <li>Each entry is a table which contains the minimum information required to tell which other package entry it corresponds to where doing a key-by-key comparison would find the appropriate package with no ambiguity (e.g. if there are two entries for the <code class="docutils literal notranslate"><span class="pre">spam</span></code> package, then you can include the version number like <code class="docutils literal notranslate"><span class="pre">{name</span> <span class="pre">=</span> <span class="pre">&quot;spam&quot;,</span> <span class="pre">version</span> <span class="pre">=</span> <span class="pre">&quot;1.0.0&quot;}</span></code>, or by source like <code class="docutils literal notranslate"><span class="pre">{name</span> <span class="pre">=</span> <span class="pre">&quot;spam&quot;,</span> <span class="pre">vcs</span> <span class="pre">=</span> <span class="pre">{</span> <span class="pre">url</span> <span class="pre">=</span> <span class="pre">&quot;...&quot;}</span></code>).</li> <li>Tools MUST NOT use this information when doing installation; it is purely informational for auditing purposes.</li> </ul> </section> <section id="packages-direct"> <h5><a class="toc-backref" href="#packages-direct" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.direct</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: boolean</li> <li><strong>Required?</strong>: no; defaults to <code class="docutils literal notranslate"><span class="pre">false</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url/#direct-url" title="(in Python Packaging User Guide)"><span>Recording the Direct URL Origin of installed distributions</span></a></li> <li>Represents whether the installation is via a <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url/#direct-url" title="(in Python Packaging User Guide)"><span class="xref std std-ref">direct URL reference</span></a>.</li> </ul> </section> <section id="packages-vcs"> <h5><a class="toc-backref" href="#packages-vcs" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.vcs]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">packages.directory</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.archive</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.sdist</span></code>, and <code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure" title="(in Python Packaging User Guide)"><span>Direct URL Data Structure</span></a></li> <li>Record the version control system details for the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-source-tree" title="(in Python Packaging User Guide)"><span class="xref std std-ref">source tree</span></a> it contains.</li> <li>Tools MAY choose to not support version control systems, both from a locking and/or installation perspective.</li> <li>Tools SHOULD provide a way for users to opt in/out of using version control systems.</li> </ul> <section id="packages-vcs-type"> <h6><a class="toc-backref" href="#packages-vcs-type" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.type</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string; supported values specified in <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-registered-vcs" title="(in Python Packaging User Guide)"><span>Registered VCS</span></a></li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-vcs" title="(in Python Packaging User Guide)"><span>VCS URLs</span></a></li> <li>The type of version control system used.</li> </ul> </section> <section id="packages-vcs-url"> <h6><a class="toc-backref" href="#packages-vcs-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.url</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: if <code class="docutils literal notranslate"><span class="pre">path</span></code> is not specified</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-vcs" title="(in Python Packaging User Guide)"><span>VCS URLs</span></a></li> <li>The URL to the source tree.</li> </ul> </section> <section id="packages-vcs-path"> <h6><a class="toc-backref" href="#packages-vcs-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.path</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: if <code class="docutils literal notranslate"><span class="pre">url</span></code> is not specified</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-vcs" title="(in Python Packaging User Guide)"><span>VCS URLs</span></a></li> <li>The path to the local directory of the source tree.</li> <li>If a relative path is used it MUST be relative to the location of this file.</li> <li>If the path is relative it MAY use POSIX-style path separators explicitly for portability.</li> </ul> </section> <section id="packages-vcs-requested-revision"> <h6><a class="toc-backref" href="#packages-vcs-requested-revision" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.requested-revision</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-vcs" title="(in Python Packaging User Guide)"><span>VCS URLs</span></a></li> <li>The branch/tag/ref/commit/revision/etc. that the user requested.</li> <li>This is purely informational and to facilitate writing the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure" title="(in Python Packaging User Guide)"><span>Direct URL Data Structure</span></a>; it MUST NOT be used to checkout the repository.</li> </ul> </section> <section id="packages-vcs-commit-id"> <h6><a class="toc-backref" href="#packages-vcs-commit-id" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.commit-id</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-vcs" title="(in Python Packaging User Guide)"><span>VCS URLs</span></a></li> <li>The exact commit/revision number that is to be installed.</li> <li>If the VCS supports commit-hash based revision identifiers, such a commit-hash MUST be used as the commit ID in order to reference an immutable version of the source code.</li> </ul> </section> <section id="packages-vcs-subdirectory"> <h6><a class="toc-backref" href="#packages-vcs-subdirectory" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.vcs.subdirectory</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-subdirectories" title="(in Python Packaging User Guide)"><span>Projects in subdirectories</span></a></li> <li>The subdirectory within the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-source-tree" title="(in Python Packaging User Guide)"><span class="xref std std-ref">source tree</span></a> where the project root of the project is (e.g. the location of the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file).</li> <li>The path MUST be relative to the root of the source tree structure.</li> </ul> </section> </section> <section id="packages-directory"> <h5><a class="toc-backref" href="#packages-directory" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.directory]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">packages.vcs</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.archive</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.sdist</span></code>, and <code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-local-directory" title="(in Python Packaging User Guide)"><span>Local directories</span></a></li> <li>Record the local directory details for the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-source-tree" title="(in Python Packaging User Guide)"><span class="xref std std-ref">source tree</span></a> it contains.</li> <li>Tools MAY choose to not support local directories, both from a locking and/or installation perspective.</li> <li>Tools SHOULD provide a way for users to opt in/out of using local directories.</li> </ul> <section id="packages-directory-path"> <h6><a class="toc-backref" href="#packages-directory-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.directory.path</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-local-directory" title="(in Python Packaging User Guide)"><span>Local directories</span></a></li> <li>The local directory where the source tree is.</li> <li>If the path is relative it MUST be relative to the location of the lock file.</li> <li>If the path is relative it MAY use POSIX-style path separators for portability.</li> </ul> </section> <section id="packages-directory-editable"> <h6><a class="toc-backref" href="#packages-directory-editable" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.directory.editable</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: boolean</li> <li><strong>Required?</strong>: no; defaults to <code class="docutils literal notranslate"><span class="pre">false</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-local-directory" title="(in Python Packaging User Guide)"><span>Local directories</span></a></li> <li>A flag representing whether the source tree should be installed as editable.</li> </ul> </section> <section id="packages-directory-subdirectory"> <h6><a class="toc-backref" href="#packages-directory-subdirectory" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.directory.subdirectory</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.vcs.subdirectory</span></code>.</p> </section> </section> <section id="packages-archive"> <h5><a class="toc-backref" href="#packages-archive" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.archive]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#direct-url-data-structure-archive" title="(in Python Packaging User Guide)"><span>Archive URLs</span></a></li> <li>An archive file containing a <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-source-tree" title="(in Python Packaging User Guide)"><span>Source trees</span></a>.</li> <li>Tools MAY choose to not support archive files, both from a locking and/or installation perspective.</li> <li>Tools SHOULD provide a way for users to opt in/out of using archive files.</li> </ul> <section id="packages-archive-url"> <h6><a class="toc-backref" href="#packages-archive-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.archive.url</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.vcs.url</span></code>.</p> </section> <section id="packages-archive-path"> <h6><a class="toc-backref" href="#packages-archive-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.archive.path</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.vcs.path</span></code>.</p> </section> <section id="packages-archive-size"> <h6><a class="toc-backref" href="#packages-archive-size" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.archive.size</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: integer</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://github.com/astral-sh/uv">uv</a>, <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#simple-repository-api" title="(in Python Packaging User Guide)"><span>Simple repository API</span></a></li> <li>The size of the archive file.</li> <li>Tools SHOULD provide the file size when reasonably possible (e.g. the file size is available via the <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Length">Content-Length</a> header from a <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD">HEAD</a> HTTP request).</li> </ul> </section> <section id="packages-archive-hashes"> <h6><a class="toc-backref" href="#packages-archive-hashes" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.archive.hashes]</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: Table of strings</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a>, <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#simple-repository-api" title="(in Python Packaging User Guide)"><span>Simple repository API</span></a></li> <li>A table listing known hash values of the file where the key is the hash algorithm and the value is the hash value.</li> <li>The table MUST contain at least one entry.</li> <li>Hash algorithm keys SHOULD be lowercase.</li> <li>At least one secure algorithm from <a class="reference external" href="https://docs.python.org/3/library/hashlib.html#hashlib.algorithms_guaranteed" title="(in Python v3.13)"><code class="xref py py-data docutils literal notranslate"><span class="pre">hashlib.algorithms_guaranteed</span></code></a> SHOULD always be included (at time of writing, sha256 specifically is recommended.</li> </ul> </section> <section id="packages-archive-subdirectory"> <h6><a class="toc-backref" href="#packages-archive-subdirectory" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.archive.subdirectory</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.vcs.subdirectory</span></code>.</p> </section> </section> <section id="packages-index"> <h5><a class="toc-backref" href="#packages-index" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.index</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>The base URL for the package index from <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#simple-repository-api" title="(in Python Packaging User Guide)"><span>Simple repository API</span></a> where the sdist and/or wheels were found (e.g. <code class="docutils literal notranslate"><span class="pre">https://pypi.org/simple/</span></code>).</li> <li>When possible, this SHOULD be specified to assist with generating <a class="reference external" href="https://www.cisa.gov/sbom">software bill of materials</a> – aka SBOMs – and to assist in finding a file if a URL ceases to be valid.</li> <li>Tools MAY support installing from an index if the URL recorded for a specific file is no longer vaild (e.g. returns a 404 HTTP error code).</li> </ul> </section> <section id="packages-sdist"> <h5><a class="toc-backref" href="#packages-sdist" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.sdist]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">packages.vcs</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.directory</span></code>, and <code class="docutils literal notranslate"><span class="pre">packages.archive</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>Details of a <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-sdist" title="(in Python Packaging User Guide)"><span>Source distribution file name</span></a> for the package.</li> <li>Tools MAY choose to not support sdist files, both from a locking and/or installation perspective.</li> <li>Tools SHOULD provide a way for users to opt in/out of using sdist files.</li> </ul> <section id="packages-sdist-name"> <h6><a class="toc-backref" href="#packages-sdist-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.name</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>The file name of the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-distribution-format-sdist" title="(in Python Packaging User Guide)"><span>Source distribution file name</span></a> file.</li> </ul> </section> <section id="packages-sdist-upload-time"> <h6><a class="toc-backref" href="#packages-sdist-upload-time" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.upload-time</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: datetime</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#simple-repository-api" title="(in Python Packaging User Guide)"><span>Simple repository API</span></a></li> <li>The time the file was uploaded.</li> <li>The date and time MUST be recorded in UTC.</li> </ul> </section> <section id="packages-sdist-url"> <h6><a class="toc-backref" href="#packages-sdist-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.url</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.url</span></code>.</p> </section> <section id="packages-sdist-path"> <h6><a class="toc-backref" href="#packages-sdist-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.path</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.path</span></code>.</p> </section> <section id="packages-sdist-size"> <h6><a class="toc-backref" href="#packages-sdist-size" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.size</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.size</span></code>.</p> </section> <section id="packages-sdist-hashes"> <h6><a class="toc-backref" href="#packages-sdist-hashes" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hashes</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.hashes</span></code>.</p> </section> </section> <section id="packages-wheels"> <h5><a class="toc-backref" href="#packages-wheels" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[[packages.wheels]]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: array of tables</li> <li><strong>Required?</strong>: no; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">packages.vcs</span></code>, <code class="docutils literal notranslate"><span class="pre">packages.directory</span></code>, and <code class="docutils literal notranslate"><span class="pre">packages.archive</span></code></li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>For recording the wheel files as specified by <a class="reference external" href="https://packaging.python.org/en/latest/specifications/binary-distribution-format/#binary-distribution-format" title="(in Python Packaging User Guide)"><span>Binary distribution format</span></a> for the package.</li> <li>Tools MUST support wheel files, both from a locking and installation perspective.</li> </ul> <section id="packages-wheels-name"> <h6><a class="toc-backref" href="#packages-wheels-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.name</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://pypi.org/project/pdm/">PDM</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, <a class="reference external" href="https://github.com/astral-sh/uv">uv</a></li> <li>The file name of the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/binary-distribution-format/#binary-distribution-format" title="(in Python Packaging User Guide)"><span>Binary distribution format</span></a> file.</li> </ul> </section> <section id="packages-wheels-upload-time"> <h6><a class="toc-backref" href="#packages-wheels-upload-time" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.upload-time</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.sdist.upload-time</span></code>.</p> </section> <section id="packages-wheels-url"> <h6><a class="toc-backref" href="#packages-wheels-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.url</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.url</span></code>.</p> </section> <section id="packages-wheels-path"> <h6><a class="toc-backref" href="#packages-wheels-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.path</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.path</span></code>.</p> </section> <section id="packages-wheels-size"> <h6><a class="toc-backref" href="#packages-wheels-size" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.size</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.size</span></code>.</p> </section> <section id="packages-wheels-hashes"> <h6><a class="toc-backref" href="#packages-wheels-hashes" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hashes</span></code></a></h6> <p>See <code class="docutils literal notranslate"><span class="pre">packages.archive.hashes</span></code>.</p> </section> </section> <section id="packages-attestation-identities"> <h5><a class="toc-backref" href="#packages-attestation-identities" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[[packages.attestation-identities]]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: array of tables</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/index-hosted-attestations/#provenance-object" title="(in Python Packaging User Guide)"><span>Provenance objects</span></a></li> <li>A recording of the attestations for <strong>any</strong> file recorded for this package.</li> <li>If available, tools SHOULD include the attestation identities found.</li> <li>Publisher-specific keys are to be included in the table as-is (i.e. top-level), following the spec at <a class="reference external" href="https://packaging.python.org/en/latest/specifications/index-hosted-attestations/#index-hosted-attestations" title="(in Python Packaging User Guide)"><span>Index hosted attestations</span></a>.</li> </ul> <section id="packages-attestation-identites-kind"> <h6><a class="toc-backref" href="#packages-attestation-identites-kind" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.attestation-identites.kind</span></code></a></h6> <ul class="simple"> <li><strong>Type</strong>: string</li> <li><strong>Required?</strong>: yes</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/index-hosted-attestations/#provenance-object" title="(in Python Packaging User Guide)"><span>Provenance objects</span></a></li> <li>The unique identity of the Trusted Publisher.</li> </ul> </section> </section> <section id="packages-tool"> <h5><a class="toc-backref" href="#packages-tool" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.tool]</span></code></a></h5> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/#pyproject-tool-table" title="(in Python Packaging User Guide)"><span>Arbitrary tool configuration: the [tool] table</span></a></li> <li>Similar usage as that of the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table from the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/#pyproject-toml-spec" title="(in Python Packaging User Guide)"><span>pyproject.toml specification</span></a>, but at the package version level instead of at the lock file level (which is also available via <code class="docutils literal notranslate"><span class="pre">[tool]</span></code>).</li> <li>Data recorded in the table MUST be disposable (i.e. it MUST NOT affect installation).</li> </ul> </section> </section> <section id="tool"> <h4><a class="toc-backref" href="#tool" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[tool]</span></code></a></h4> <ul class="simple"> <li><strong>Type</strong>: table</li> <li><strong>Required?</strong>: no</li> <li><strong>Inspiration</strong>: <a class="reference external" href="https://packaging.python.org/en/latest/specifications/pyproject-toml/#pyproject-tool-table" title="(in Python Packaging User Guide)"><span>Arbitrary tool configuration: the [tool] table</span></a></li> <li>See <code class="docutils literal notranslate"><span class="pre">packages.tool</span></code>.</li> </ul> </section> </section> <section id="example"> <h3><a class="toc-backref" href="#example" role="doc-backlink">Example</a></h3> <div class="highlight-TOML notranslate"><div class="highlight"><pre><span></span><span class="n">metadata-version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;1.0&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.9&quot;</span> <span class="n">created-by</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;PEP 751&quot;</span> <span class="k">[[packages]]</span> <span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;attrs&quot;</span> <span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;23.2.0&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.7&quot;</span> <span class="n">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://pypi.org/simple/&quot;</span> <span class="n">wheels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;attrs-23.2.0-py3-none-any.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2023-12-31T06:30:30.772444Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">60752</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">}</span> <span class="p">]</span> <span class="k">[[packages]]</span> <span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;cattrs&quot;</span> <span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;23.2.3&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.8&quot;</span> <span class="n">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://pypi.org/simple/&quot;</span> <span class="n">wheels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;cattrs-23.2.3-py3-none-any.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2023-11-30T22:19:19.163763Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/b3/0d/cd4a4071c7f38385dc5ba91286723b4d1090b87815db48216212c6c6c30e/cattrs-23.2.3-py3-none-any.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">57474</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;0341994d94971052e9ee70662542699a3162ea1e0c62f7ce1b4a57f563685108&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">}</span> <span class="p">]</span> <span class="k">[[packages]]</span> <span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;numpy&quot;</span> <span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;2.0.1&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.9&quot;</span> <span class="n">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://pypi.org/simple/&quot;</span> <span class="n">wheels</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:15.810939Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/64/1c/401489a7e92c30db413362756c313b9353fb47565015986c55582593e2ae/numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">20965374</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:36.460324Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/08/61/460fb524bb2d1a8bd4bbcb33d9b0971f9837fdedcfda8478d4c8f5cfd7ee/numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">13102536</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:46.601144Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/c2/da/3d8debb409bc97045b559f408d2b8cefa6a077a73df14dbf4d8780d976b1/numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">5037809</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:58.784393Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/6d/59/85160bf5f4af6264a7c5149ab07be9c8db2b0eb064794f8a7bf6d/numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">6631813</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:38:19.714559Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/5e/e3/944b77e2742fece7da8dfba6f7ef7dccdd163d1a613f7027f4d5b/numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">13623742</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:38:48.972569Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/2c/f3/61eee37decb58e7cb29940f19a1464b8608f2cab8a8616aba75fd/numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">19242336</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:19.213811Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/77/b5/c74cc436114c1de5912cdb475145245f6e645a6a1a29b5d08c774/numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">19637264</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:41.812321Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/da/89/c8856e12e0b3f6af371ccb90d604600923b08050c58f0cd26eac9/numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">14108911</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-win32.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:52.932102Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/15/96/310c6f6d146518479b0a6ee6eb92a537954ec3b1acfa2894d1347/numpy-2.0.1-cp312-cp312-win32.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">6171379</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="w"> </span><span class="p">{</span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;numpy-2.0.1-cp312-cp312-win_amd64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:40:17.532627Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/b5/59/f6ad378ad85ed9c2785f271b39c3e5b6412c66e810d2c60934c9f/numpy-2.0.1-cp312-cp312-win_amd64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">16255757</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171&quot;</span><span class="p">}</span><span class="w"> </span><span class="p">},</span> <span class="p">]</span> </pre></div> </div> </section> <section id="installation"> <h3><a class="toc-backref" href="#installation" role="doc-backlink">Installation</a></h3> <p>The following outlines the steps to be taken to install from a lock file (while the requirements are prescriptive, the general steps and order are a suggestion):</p> <ol class="arabic simple"> <li>Check if the metadata version specified by <code class="docutils literal notranslate"><span class="pre">lock-version</span></code> is supported; an error or warning MUST be raised as appropriate.</li> <li>If <code class="docutils literal notranslate"><span class="pre">requires-python</span></code> is specified, check that the environment being installed for meets the requirement; an error MUST be raised if it is not met.</li> <li>If <code class="docutils literal notranslate"><span class="pre">environments</span></code> is specified, check that at least one of the environment marker expressions is satisfied; an error MUST be raised if no expression is satisfied.</li> <li>For each package listed in <code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code>:<ol class="arabic simple"> <li>If <code class="docutils literal notranslate"><span class="pre">marker</span></code> is specified, check if it is satisfied; if it isn’t, skip to the next package.</li> <li>If <code class="docutils literal notranslate"><span class="pre">requires-python</span></code> is specified, check if it is satisfied; an error MUST be raised if it isn’t.</li> <li>Check that no other instance of the package has been slated to be installed; an error about the ambiguity MUST be raised otherwise.</li> <li>Check that the source of the package is specified appropriately (i.e. there are not conflicting sources in the package entry); an error MUST be raised if any issues are found.</li> <li>Add the package to the set of packages to install.</li> </ol> </li> <li>For each package to be installed:<ul class="simple"> <li>If <code class="docutils literal notranslate"><span class="pre">vcs</span></code> is set:<ol class="arabic simple"> <li>Clone the repository to the commit ID specified in <code class="docutils literal notranslate"><span class="pre">commit-id</span></code>.</li> <li>Build the package, respecting <code class="docutils literal notranslate"><span class="pre">subdirectory</span></code>.</li> <li>Install.</li> </ol> </li> <li>Else if <code class="docutils literal notranslate"><span class="pre">directory</span></code> is set:<ol class="arabic simple"> <li>Build the package, respecting <code class="docutils literal notranslate"><span class="pre">subdirectory</span></code>.</li> <li>Install.</li> </ol> </li> <li>Else if <code class="docutils literal notranslate"><span class="pre">archive</span></code> is set:<ol class="arabic simple"> <li>Get the file.</li> <li>Validate the file size and hash.</li> <li>Build the package, respecting <code class="docutils literal notranslate"><span class="pre">subdirectory</span></code>.</li> <li>Install.</li> </ol> </li> <li>Else if there are entries for <code class="docutils literal notranslate"><span class="pre">wheels</span></code>:<ol class="arabic simple"> <li>Look for the appropriate wheel file based on <code class="docutils literal notranslate"><span class="pre">name</span></code>; if one is not found then move on to <code class="docutils literal notranslate"><span class="pre">sdist</span></code> or an error MUST be raised about a lack of source for the project.</li> <li>Get the file:<ul> <li>If <code class="docutils literal notranslate"><span class="pre">path</span></code> is set, use it.</li> <li>If <code class="docutils literal notranslate"><span class="pre">url</span></code> is set, try to use it; optionally tools MAY use <code class="docutils literal notranslate"><span class="pre">packages.index</span></code> or some tool-specific mechanism to download the selected wheel file (tools MUST NOT try to change what wheel file to download based on what’s available; what file to install should be determined in an offline fashion for reproducibility).</li> </ul> </li> <li>Validate the file size and hash.</li> <li>Install.</li> </ol> </li> <li>Else if no <code class="docutils literal notranslate"><span class="pre">wheel</span></code> file is found or <code class="docutils literal notranslate"><span class="pre">sdist</span></code> is solely set:<ol class="arabic simple"> <li>Get the file.<ul> <li>If <code class="docutils literal notranslate"><span class="pre">path</span></code> is set, use it.</li> <li>If <code class="docutils literal notranslate"><span class="pre">url</span></code> is set, try to use it; tools MAY use <code class="docutils literal notranslate"><span class="pre">packages.index</span></code> or some tool-specific mechanism to download the file.</li> </ul> </li> <li>Validate the file size and hash.</li> <li>Build the package.</li> <li>Install.</li> </ol> </li> </ul> </li> </ol> </section> <section id="semantic-differences-with-requirements-txt-files"> <h3><a class="toc-backref" href="#semantic-differences-with-requirements-txt-files" role="doc-backlink">Semantic differences with <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code> files</a></h3> <p>Ignoring formatting, there are a few differences between lock files as proposed by this PEP and those that are possible via a <a class="reference external" href="https://pip.pypa.io/en/stable/reference/requirements-file-format/">requirements file</a>.</p> <p>Some of the differences are in regards to security. Requiring hashes, recording file sizes, and where a file was found – both the index and the location of the file itself – help with auditing and validating the files that were locked against. Compare that with requirements files which can optionally include hashes, but it is an opt-in feature and can be bypassed. The optional inclusion of a file’s upload time and where the files can be found is also different.</p> <p>Being explicit about the supported Python versions and environments for the file overall is also unique to this PEP. This is to alleviate the issue of not knowing when a requirements file targets a specific platform.</p> <p>The <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> tables don’t have a direct correlation in requirements files. They do support comments, but they are not inherently structured like the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table is thanks to being in TOML.</p> <p>While comments in a requirements file could record details that are helpful for auditing and understanding what the lock file contains, providing the structured support to record such things makes auditing easier. Recording the required Python version for a package upfront helps with this as well as erroring out sooner if an install is going to fail. Recording the wheel file name separate from the URL or path is also to help make reading the list of wheel files easier as it encodes information that can be useful when understanding and auditing a file. Recording the sdist file name is for the same reason.</p> </section> </section> <section id="backwards-compatibility"> <h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2> <p>Because there is no preexisting lock file format, there are no explicit backwards-compatibility concerns in terms of Python packaging standards.</p> <p>As for packaging tools themselves, that will be a per-tool decision as to whether they choose to support this PEP and in what way (i.e. as an export target or as the primary way they record their lock file).</p> </section> <section id="security-implications"> <h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2> <p>The hope is that by standardizing on a lock file format which starts from a security-first posture it will help make overall packaging installation safer. However, this PEP does not solve all potential security concerns.</p> <p>One potential concern is tampering with a lock file. If a lock file is not kept in source control and properly audited, a bad actor could change the file in nefarious ways (e.g., point to a malware version of a package). Tampering could also occur in transit to e.g. a cloud provider who will perform an installation on the user’s behalf. Both could be mitigated by signing the lock file either within the file in a <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> entry or via a side channel external to the lock file itself.</p> <p>This PEP does not do anything to prevent a user from installing incorrect packages. While including many details to help in auditing a package’s inclusion, there isn’t any mechanism to stop e.g. name confusion attacks via typosquatting. Tools may be able to provide some UX to help with this (e.g. by providing download counts for a package).</p> </section> <section id="how-to-teach-this"> <h2><a class="toc-backref" href="#how-to-teach-this" role="doc-backlink">How to Teach This</a></h2> <p>Users should be informed that when they ask to install some package, the package may have its own dependencies, those dependencies may have dependencies, and so on. Without writing down what gets installed as part of installing the package they requested, things could change from underneath them (e.g. package versions). Changes to the underlying dependencies can lead to accidental breakage of their code. Lock files help deal with that by providing a way to write down what was installed so you can install the exact same thing in the future.</p> <p>Having what to install written down also helps in collaborating with others. By agreeing to a lock file’s contents, everyone ends up with the same packages installed. This helps make sure no one relies on e.g. an API that’s only available in a certain version that not everyone working on the project has installed.</p> <p>Lock files also help with security by making sure you always get the same files installed and not a malicious one that someone may have slipped in. It also lets one be more deliberate in upgrading their dependencies and thus making sure the change is on purpose and not one slipped in by a bad actor.</p> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>A proof-of-concept implementing most of this PEP for various versions of this PEP can be found at <a class="reference external" href="https://github.com/brettcannon/mousebender/tree/pep">https://github.com/brettcannon/mousebender/tree/pep</a> . While the various implementations have not matched the exact format of this PEP, the general semantic requirements have been implemented before.</p> <p>Prior to acceptance of this PEP, the PoC will be updated.</p> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <section id="recording-the-dependency-graph-for-installation-purposes"> <h3><a class="toc-backref" href="#recording-the-dependency-graph-for-installation-purposes" role="doc-backlink">Recording the dependency graph for installation purposes</a></h3> <p>A previous version of this PEP recorded the dependency graph of packages instead of a set of packages to install. The idea was that by recording the dependency graph you not only got more information, but it provided more flexibility by supporting more features innately (e.g. platform-specific dependencies without explicitly propagating markers).</p> <p>In the end, though, it was deemed to add complexity that wasn’t worth the cost (e.g. it impacted the ease of auditing for details which were not necessary for this PEP to reach its goals).</p> </section> <section id="specifying-a-new-core-metadata-version-that-requires-consistent-metadata-across-files"> <h3><a class="toc-backref" href="#specifying-a-new-core-metadata-version-that-requires-consistent-metadata-across-files" role="doc-backlink">Specifying a new core metadata version that requires consistent metadata across files</a></h3> <p>At one point, to handle the issue of metadata varying between files and thus require examining every released file for a package and version for accurate locking results, the idea was floated to introduce a new core metadata version which would require all metadata for all wheel files be the same for a single version of a package. Ultimately, though, it was deemed unnecessary as this PEP will put pressure on people to make files consistent for performance reasons or to make indexes provide all the metadata separate from the wheel files themselves. As well, there’s no easy enforcement mechanism, and so community expectation would work as well as a new metadata version.</p> </section> <section id="have-the-installer-do-dependency-resolution"> <h3><a class="toc-backref" href="#have-the-installer-do-dependency-resolution" role="doc-backlink">Have the installer do dependency resolution</a></h3> <p>In order to support a format more akin to how Poetry worked when this PEP was drafted, it was suggested that lockers effectively record the packages and their versions which may be necessary to make an install work in any possible scenario, and then the installer resolves what to install. But that complicates auditing a lock file by requiring much more mental effort to know what packages may be installed in any given scenario. Also, one of the Poetry developers <a class="reference external" href="https://discuss.python.org/t/lock-files-again-but-this-time-w-sdists/46593/83">suggested</a> that markers as represented in the package locking approach of this PEP may be sufficient to cover the needs of Poetry. Not having the installer do a resolution also simplifies their implementation, centralizing complexity in lockers.</p> </section> <section id="requiring-minimum-hash-algorithm-support"> <h3><a class="toc-backref" href="#requiring-minimum-hash-algorithm-support" role="doc-backlink">Requiring minimum hash algorithm support</a></h3> <p>It was proposed to require a baseline hash algorithm for the files. This was rejected as no other Python packaging specification requires specific hash algorithm support. As well, the minimum hash algorithm suggested may eventually become an outdated/unsafe suggestion, requiring further updates. In order to promote using the best algorithm at all times, no baseline is provided to avoid simply defaulting to the baseline in tools without considering the security ramifications of that hash algorithm.</p> </section> <section id="file-naming"> <h3><a class="toc-backref" href="#file-naming" role="doc-backlink">File naming</a></h3> <section id="using-pylock-toml-as-the-file-name"> <h4><a class="toc-backref" href="#using-pylock-toml-as-the-file-name" role="doc-backlink">Using <code class="docutils literal notranslate"><span class="pre">*.pylock.toml</span></code> as the file name</a></h4> <p>It was proposed to put the <code class="docutils literal notranslate"><span class="pre">pylock</span></code> constant part of the file name after the identifier for the purpose of the lock file. It was decided not to do this so that lock files would sort together when looking at directory contents instead of purely based on their purpose which could spread them out in a directory.</p> </section> <section id="using-pylock-as-the-file-name"> <h4><a class="toc-backref" href="#using-pylock-as-the-file-name" role="doc-backlink">Using <code class="docutils literal notranslate"><span class="pre">*.pylock</span></code> as the file name</a></h4> <p>Not using <code class="docutils literal notranslate"><span class="pre">.toml</span></code> as the file extension and instead making it <code class="docutils literal notranslate"><span class="pre">.pylock</span></code> itself was proposed. This was decided against so that code editors would know how to provide syntax highlighting to a lock file without having special knowledge about the file extension.</p> </section> <section id="not-having-a-naming-convention-for-the-file"> <h4><a class="toc-backref" href="#not-having-a-naming-convention-for-the-file" role="doc-backlink">Not having a naming convention for the file</a></h4> <p>Having no requirements or guidance for a lock file’s name was considered, but ultimately rejected. By having a standardized naming convention it makes it easy to identify a lock file for both a human and a code editor. This helps facilitate discovery when e.g. a tool wants to know all of the lock files that are available.</p> </section> </section> <section id="id1"> <h3><a class="toc-backref" href="#id1" role="doc-backlink">File format</a></h3> <section id="use-json-over-toml"> <h4><a class="toc-backref" href="#use-json-over-toml" role="doc-backlink">Use JSON over TOML</a></h4> <p>Since having a format that is machine-writable was a goal of this PEP, it was suggested to use JSON. But it was deemed less human-readable than TOML while not improving on the machine-writable aspect enough to warrant the change.</p> </section> <section id="use-yaml-over-toml"> <h4><a class="toc-backref" href="#use-yaml-over-toml" role="doc-backlink">Use YAML over TOML</a></h4> <p>Some argued that YAML met the machine-writable/human-readable requirement in a better way than TOML. But as that’s subjective and <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> already existed as the human-writable file used by Python packaging standards it was deemed more important to keep using TOML.</p> </section> </section> <section id="other-keys"> <h3><a class="toc-backref" href="#other-keys" role="doc-backlink">Other keys</a></h3> <section id="a-single-hash-algorithm-for-the-whole-file"> <h4><a class="toc-backref" href="#a-single-hash-algorithm-for-the-whole-file" role="doc-backlink">A single hash algorithm for the whole file</a></h4> <p>Earlier versions of this PEP proposed having a single hash algorithm be specified per file instead of any number of algorithms per file. The thinking was that by specifying a single algorithm it would help with auditing the file when a specific hash algorithm was mandated for use.</p> <p>In the end there was some objection to this idea. Typically, it centered around the cost of rehashing large wheel files (e.g. PyTorch). There was also concern about making hashing decisions upfront on the installer’s behalf which they may disagree with. In the end it was deemed better to have flexibility and let people audit the lock file as they see fit.</p> </section> <section id="hashing-the-contents-of-the-lock-file-itself"> <h4><a class="toc-backref" href="#hashing-the-contents-of-the-lock-file-itself" role="doc-backlink">Hashing the contents of the lock file itself</a></h4> <p>Hashing the contents of the bytes of the file and storing hash value within the file itself was proposed at some point. This was removed to make it easier when merging changes to the lock file as each merge would have to recalculate the hash value to avoid a merge conflict.</p> <p>Hashing the semantic contents of the file was also proposed, but it would lead to the same merge conflict issue.</p> <p>Regardless of which contents were hashed, either approach could have the hash value stored outside of the file if such a hash was desired.</p> </section> <section id="recording-the-creation-date-of-the-lock-file"> <h4><a class="toc-backref" href="#recording-the-creation-date-of-the-lock-file" role="doc-backlink">Recording the creation date of the lock file</a></h4> <p>To know how potentially stale the lock file was, an earlier proposal suggested recording the creation date of the lock file. But for some same merge conflict reasons as storing the hash of the file contents, this idea was dropped.</p> </section> <section id="recording-the-package-indexes-used-in-searching"> <h4><a class="toc-backref" href="#recording-the-package-indexes-used-in-searching" role="doc-backlink">Recording the package indexes used in searching</a></h4> <p>Recording what package indexes were used to create the lock file was considered. In the end, though, it was rejected as it was deemed unnecessary bookkeeping.</p> </section> <section id="locking-build-requirements-for-sdists"> <h4><a class="toc-backref" href="#locking-build-requirements-for-sdists" role="doc-backlink">Locking build requirements for sdists</a></h4> <p>An earlier version of this PEP tried to lock the build requirements for sdists under a <code class="docutils literal notranslate"><span class="pre">packages.build-requires</span></code> key. Unfortunately, it confused enough people about how it was expected to operate and there were enough edge case issues to decide it wasn’t worth trying to do in this PEP upfront. Instead, a future PEP could propose a solution.</p> </section> <section id="recording-possible-extras-and-dependency-groups"> <h4><a class="toc-backref" href="#recording-possible-extras-and-dependency-groups" role="doc-backlink">Recording possible extras and dependency groups</a></h4> <p>To expand the feature set of this PEP such that tools could use this PEP for their main lock file format, recording possible extras and dependency groups that a user may request was considered. The idea was that if you were locking from a <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file then you would want to lock for all possibilities; that includes extras and dependency groups.</p> <p>To make this work one would need a way to declare when a package applied to an extra and/or dependency group. Due to the possibility that a combination of extras and/or dependency groups could change version requirements of a package (e.g. extra A needed the spam package at any version, but extra B needed the spam package older than version 2, thus making whether extra B was requested override what extra A requested), it would require either full Boolean logic support or only locking to a specific version of a package no matter what extras and/or dependency groups were requested. The former would at least require coming up with semantics around a marker for dependency groups, and the latter would require a separate lock file any time one didn’t want a single version restriction.</p> <p>In the end, there wasn’t enough interest from tools for using this PEP as their sole lock file format to warrant doing the work to implement this feature at this time.</p> </section> </section> <section id="simplification"> <h3><a class="toc-backref" href="#simplification" role="doc-backlink">Simplification</a></h3> <section id="drop-recording-the-package-version"> <h4><a class="toc-backref" href="#drop-recording-the-package-version" role="doc-backlink">Drop recording the package version</a></h4> <p>The package version is optional since it can only be reliably recorded when an sdist of wheel file is used. And since both sources record the version in file names it is technically redundant.</p> <p>But in discussions it was decided the version number is useful for auditing enough to still state it separately.</p> </section> <section id="drop-the-requirement-to-specify-the-location-of-an-sdist-and-or-wheels"> <h4><a class="toc-backref" href="#drop-the-requirement-to-specify-the-location-of-an-sdist-and-or-wheels" role="doc-backlink">Drop the requirement to specify the location of an sdist and/or wheels</a></h4> <p>At least one person has commented how their work has unstable URLs for all sdists and wheels. As such, they have to search for all files at install regardless of where the file was found previously. Dropping the requirement to provide the URL or path to a file would have helped solve the issue of recording known-bad information.</p> <p>The decision to allow tools to look for a file in other ways beyond the URL provided alleviated the need to make the URL optional.</p> </section> <section id="drop-requiring-file-size-and-hashes"> <h4><a class="toc-backref" href="#drop-requiring-file-size-and-hashes" role="doc-backlink">Drop requiring file size and hashes</a></h4> <p>At least one person has said that their work modifies all wheels and sdists with internal files. That means any recorded hashes and file sizes will be wrong. By making the file size and hashes optional – very likely through some opt-out mechanism – then they could continue to produce lock files that meet this PEP’s requirements.</p> <p>The decision was made that this weakens security too much. It also prevents installing files from alternative locations.</p> </section> <section id="drop-recording-the-sdist-file-name"> <h4><a class="toc-backref" href="#drop-recording-the-sdist-file-name" role="doc-backlink">Drop recording the sdist file name</a></h4> <p>While incompatible with dropping the URL/path requirement, the package version, and hashes, recording the sdist file name is technically not necessary at all (right now recording the file name is optional). The file name only encodes the project name and version, so no new info is conveyed about the file (when the package version is provided). And if the location is recorded then getting the file is handled regardless of the file name.</p> <p>But recording the file name can helpful when looking for an appropriate file when the recorded file location is no longer available (while sdist file names are now standardized thanks to <a class="pep reference internal" href="../pep-0625/" title="PEP 625 – Filename of a Source Distribution">PEP 625</a>, that has only been true since 2020 and thus there are many older sdists with names that may not be guessable).</p> <p>The decision was made to require the sdist file name out of simplicity.</p> </section> <section id="make-packages-wheels-a-table"> <h4><a class="toc-backref" href="#make-packages-wheels-a-table" role="doc-backlink">Make <code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code> a table</a></h4> <p>One could see writing out wheel file details as a table keyed on the file name. For example:</p> <div class="highlight-TOML notranslate"><div class="highlight"><pre><span></span><span class="k">[[packages]]</span> <span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;attrs&quot;</span> <span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;23.2.0&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.7&quot;</span> <span class="n">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://pypi.org/simple/&quot;</span> <span class="k">[packages.wheels]</span> <span class="s2">&quot;attrs-23.2.0-py3-none-any.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2023-12-31T06:30:30.772444Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">60752</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1&quot;</span><span class="p">}</span> <span class="k">[[packages]]</span> <span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;numpy&quot;</span> <span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;2.0.1&quot;</span> <span class="n">requires-python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;&gt;=3.9&quot;</span> <span class="n">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;https://pypi.org/simple/&quot;</span> <span class="k">[packages.wheels]</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:15.810939Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/64/1c/401489a7e92c30db413362756c313b9353fb47565015986c55582593e2ae/numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">20965374</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:36.460324Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/08/61/460fb524bb2d1a8bd4bbcb33d9b0971f9837fdedcfda8478d4c8f5cfd7ee/numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">13102536</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:46.601144Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/c2/da/3d8debb409bc97045b559f408d2b8cefa6a077a73df14dbf4d8780d976b1/numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">5037809</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:37:58.784393Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/6d/59/85160bf5f4af6264a7c5149ab07be9c8db2b0eb064794f8a7bf6d/numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">6631813</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:38:19.714559Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/5e/e3/944b77e2742fece7da8dfba6f7ef7dccdd163d1a613f7027f4d5b/numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">13623742</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:38:48.972569Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/2c/f3/61eee37decb58e7cb29940f19a1464b8608f2cab8a8616aba75fd/numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">19242336</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:19.213811Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/77/b5/c74cc436114c1de5912cdb475145245f6e645a6a1a29b5d08c774/numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">19637264</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:41.812321Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/da/89/c8856e12e0b3f6af371ccb90d604600923b08050c58f0cd26eac9/numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">14108911</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-win32.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:39:52.932102Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/15/96/310c6f6d146518479b0a6ee6eb92a537954ec3b1acfa2894d1347/numpy-2.0.1-cp312-cp312-win32.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">6171379</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf&quot;</span><span class="p">}</span> <span class="s2">&quot;numpy-2.0.1-cp312-cp312-win_amd64.whl&quot;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="n">upload-time</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="ld">2024-07-21T13:40:17.532627Z</span><span class="p">,</span><span class="w"> </span><span class="n">url</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;https://files.pythonhosted.org/packages/b5/59/f6ad378ad85ed9c2785f271b39c3e5b6412c66e810d2c60934c9f/numpy-2.0.1-cp312-cp312-win_amd64.whl&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mi">16255757</span><span class="p">,</span><span class="w"> </span><span class="n">hashes</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">{</span><span class="n">sha256</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s2">&quot;bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171&quot;</span><span class="p">}</span> </pre></div> </div> <p>In general, though, people did not prefer this over the approach this PEP has taken.</p> </section> </section> <section id="self-referential"> <h3><a class="toc-backref" href="#self-referential" role="doc-backlink">Self-Referential</a></h3> <section id="drop-the-tool-table"> <h4><a class="toc-backref" href="#drop-the-tool-table" role="doc-backlink">Drop the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table</a></h4> <p>The <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table is included as it has been found to be very useful for <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> files. Providing similar flexibility to this PEP is done in hopes that similar benefits will materialize.</p> <p>But some people have been concerned that such a table will be too enticing to tools and will lead to files that are tool-specific and unusable by other tools. This could cause issues for tools trying to do installation, auditing, etc. as they would not know what details in the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table are somehow critical.</p> <p>As a compromise, this PEP specifies that the details recorded in <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> must be disposable and not affect installation of packages.</p> </section> <section id="list-the-requirement-inputs-for-the-file"> <h4><a class="toc-backref" href="#list-the-requirement-inputs-for-the-file" role="doc-backlink">List the requirement inputs for the file</a></h4> <p>Right now the file does not record the requirements that acted as inputs to the file. This is for simplicity reasons and to not explicitly constrain the file in some unforeseen way (e.g., updating the file after initial creation for a new platform that has different requirements, all without having to resolve how to write a comprehensive set of requirements).</p> <p>But it may help in auditing and any recreation of the file if the original requirements were somehow recorded. This could be a single string or an array of strings if multiple requirements were used with the file.</p> <p>In the end it was deemed too complicated to try and capture the inputs that a tool used to construct the lock file in a generic fashion.</p> </section> </section> <section id="auditing"> <h3><a class="toc-backref" href="#auditing" role="doc-backlink">Auditing</a></h3> <section id="recording-dependents"> <h4><a class="toc-backref" href="#recording-dependents" role="doc-backlink">Recording dependents</a></h4> <p>Recording the dependents of a package is not necessary to install it. As such, it has been left out of the PEP as it can be included via <code class="docutils literal notranslate"><span class="pre">[tool]</span></code>.</p> <p>But knowing how critical a package is to other packages may be beneficial. This information is included by <a class="reference external" href="https://pypi.org/project/pip-tools/">pip-tools</a> , so there’s prior art in including it. A flexible approach could be used to record the dependents, e.g. as much detail as to differentiate from any other entry for the same package in the file (inspired by <a class="reference external" href="https://github.com/astral-sh/uv">uv</a>).</p> <p>In the end, though, it was decided that recording the dependencies is a better thing to record.</p> </section> </section> </section> <section id="acknowledgements"> <h2><a class="toc-backref" href="#acknowledgements" role="doc-backlink">Acknowledgements</a></h2> <p>Thanks to everyone who participated in the discussions on discuss.python.org. Also thanks to Randy Döring, Seth Michael Larson, Paul Moore, and Ofek Lev for providing feedback on a draft version of this PEP before going public.</p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0751.rst">https://github.com/python/peps/blob/main/peps/pep-0751.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0751.rst">2025-02-07 20:35:58 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#motivation">Motivation</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#specification">Specification</a><ul> <li><a class="reference internal" href="#file-name">File Name</a></li> <li><a class="reference internal" href="#file-format">File Format</a><ul> <li><a class="reference internal" href="#lock-version"><code class="docutils literal notranslate"><span class="pre">lock-version</span></code></a></li> <li><a class="reference internal" href="#environments"><code class="docutils literal notranslate"><span class="pre">environments</span></code></a></li> <li><a class="reference internal" href="#requires-python"><code class="docutils literal notranslate"><span class="pre">requires-python</span></code></a></li> <li><a class="reference internal" href="#created-by"><code class="docutils literal notranslate"><span class="pre">created-by</span></code></a></li> <li><a class="reference internal" href="#packages"><code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code></a><ul> <li><a class="reference internal" href="#packages-name"><code class="docutils literal notranslate"><span class="pre">packages.name</span></code></a></li> <li><a class="reference internal" href="#packages-version"><code class="docutils literal notranslate"><span class="pre">packages.version</span></code></a></li> <li><a class="reference internal" href="#packages-marker"><code class="docutils literal notranslate"><span class="pre">packages.marker</span></code></a></li> <li><a class="reference internal" href="#packages-requires-python"><code class="docutils literal notranslate"><span class="pre">packages.requires-python</span></code></a></li> <li><a class="reference internal" href="#packages-dependencies"><code class="docutils literal notranslate"><span class="pre">[[packages.dependencies]]</span></code></a></li> <li><a class="reference internal" href="#packages-direct"><code class="docutils literal notranslate"><span class="pre">packages.direct</span></code></a></li> <li><a class="reference internal" href="#packages-vcs"><code class="docutils literal notranslate"><span class="pre">[packages.vcs]</span></code></a><ul> <li><a class="reference internal" href="#packages-vcs-type"><code class="docutils literal notranslate"><span class="pre">packages.vcs.type</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-url"><code class="docutils literal notranslate"><span class="pre">packages.vcs.url</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-path"><code class="docutils literal notranslate"><span class="pre">packages.vcs.path</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-requested-revision"><code class="docutils literal notranslate"><span class="pre">packages.vcs.requested-revision</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-commit-id"><code class="docutils literal notranslate"><span class="pre">packages.vcs.commit-id</span></code></a></li> <li><a class="reference internal" href="#packages-vcs-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.vcs.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-directory"><code class="docutils literal notranslate"><span class="pre">[packages.directory]</span></code></a><ul> <li><a class="reference internal" href="#packages-directory-path"><code class="docutils literal notranslate"><span class="pre">packages.directory.path</span></code></a></li> <li><a class="reference internal" href="#packages-directory-editable"><code class="docutils literal notranslate"><span class="pre">packages.directory.editable</span></code></a></li> <li><a class="reference internal" href="#packages-directory-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.directory.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-archive"><code class="docutils literal notranslate"><span class="pre">[packages.archive]</span></code></a><ul> <li><a class="reference internal" href="#packages-archive-url"><code class="docutils literal notranslate"><span class="pre">packages.archive.url</span></code></a></li> <li><a class="reference internal" href="#packages-archive-path"><code class="docutils literal notranslate"><span class="pre">packages.archive.path</span></code></a></li> <li><a class="reference internal" href="#packages-archive-size"><code class="docutils literal notranslate"><span class="pre">packages.archive.size</span></code></a></li> <li><a class="reference internal" href="#packages-archive-hashes"><code class="docutils literal notranslate"><span class="pre">[packages.archive.hashes]</span></code></a></li> <li><a class="reference internal" href="#packages-archive-subdirectory"><code class="docutils literal notranslate"><span class="pre">packages.archive.subdirectory</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-index"><code class="docutils literal notranslate"><span class="pre">packages.index</span></code></a></li> <li><a class="reference internal" href="#packages-sdist"><code class="docutils literal notranslate"><span class="pre">[packages.sdist]</span></code></a><ul> <li><a class="reference internal" href="#packages-sdist-name"><code class="docutils literal notranslate"><span class="pre">packages.sdist.name</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-upload-time"><code class="docutils literal notranslate"><span class="pre">packages.sdist.upload-time</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-url"><code class="docutils literal notranslate"><span class="pre">packages.sdist.url</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-path"><code class="docutils literal notranslate"><span class="pre">packages.sdist.path</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-size"><code class="docutils literal notranslate"><span class="pre">packages.sdist.size</span></code></a></li> <li><a class="reference internal" href="#packages-sdist-hashes"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hashes</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-wheels"><code class="docutils literal notranslate"><span class="pre">[[packages.wheels]]</span></code></a><ul> <li><a class="reference internal" href="#packages-wheels-name"><code class="docutils literal notranslate"><span class="pre">packages.wheels.name</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-upload-time"><code class="docutils literal notranslate"><span class="pre">packages.wheels.upload-time</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-url"><code class="docutils literal notranslate"><span class="pre">packages.wheels.url</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-path"><code class="docutils literal notranslate"><span class="pre">packages.wheels.path</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-size"><code class="docutils literal notranslate"><span class="pre">packages.wheels.size</span></code></a></li> <li><a class="reference internal" href="#packages-wheels-hashes"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hashes</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-attestation-identities"><code class="docutils literal notranslate"><span class="pre">[[packages.attestation-identities]]</span></code></a><ul> <li><a class="reference internal" href="#packages-attestation-identites-kind"><code class="docutils literal notranslate"><span class="pre">packages.attestation-identites.kind</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#packages-tool"><code class="docutils literal notranslate"><span class="pre">[packages.tool]</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#tool"><code class="docutils literal notranslate"><span class="pre">[tool]</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#example">Example</a></li> <li><a class="reference internal" href="#installation">Installation</a></li> <li><a class="reference internal" href="#semantic-differences-with-requirements-txt-files">Semantic differences with <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code> files</a></li> </ul> </li> <li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li> <li><a class="reference internal" href="#security-implications">Security Implications</a></li> <li><a class="reference internal" href="#how-to-teach-this">How to Teach This</a></li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#recording-the-dependency-graph-for-installation-purposes">Recording the dependency graph for installation purposes</a></li> <li><a class="reference internal" href="#specifying-a-new-core-metadata-version-that-requires-consistent-metadata-across-files">Specifying a new core metadata version that requires consistent metadata across files</a></li> <li><a class="reference internal" href="#have-the-installer-do-dependency-resolution">Have the installer do dependency resolution</a></li> <li><a class="reference internal" href="#requiring-minimum-hash-algorithm-support">Requiring minimum hash algorithm support</a></li> <li><a class="reference internal" href="#file-naming">File naming</a><ul> <li><a class="reference internal" href="#using-pylock-toml-as-the-file-name">Using <code class="docutils literal notranslate"><span class="pre">*.pylock.toml</span></code> as the file name</a></li> <li><a class="reference internal" href="#using-pylock-as-the-file-name">Using <code class="docutils literal notranslate"><span class="pre">*.pylock</span></code> as the file name</a></li> <li><a class="reference internal" href="#not-having-a-naming-convention-for-the-file">Not having a naming convention for the file</a></li> </ul> </li> <li><a class="reference internal" href="#id1">File format</a><ul> <li><a class="reference internal" href="#use-json-over-toml">Use JSON over TOML</a></li> <li><a class="reference internal" href="#use-yaml-over-toml">Use YAML over TOML</a></li> </ul> </li> <li><a class="reference internal" href="#other-keys">Other keys</a><ul> <li><a class="reference internal" href="#a-single-hash-algorithm-for-the-whole-file">A single hash algorithm for the whole file</a></li> <li><a class="reference internal" href="#hashing-the-contents-of-the-lock-file-itself">Hashing the contents of the lock file itself</a></li> <li><a class="reference internal" href="#recording-the-creation-date-of-the-lock-file">Recording the creation date of the lock file</a></li> <li><a class="reference internal" href="#recording-the-package-indexes-used-in-searching">Recording the package indexes used in searching</a></li> <li><a class="reference internal" href="#locking-build-requirements-for-sdists">Locking build requirements for sdists</a></li> <li><a class="reference internal" href="#recording-possible-extras-and-dependency-groups">Recording possible extras and dependency groups</a></li> </ul> </li> <li><a class="reference internal" href="#simplification">Simplification</a><ul> <li><a class="reference internal" href="#drop-recording-the-package-version">Drop recording the package version</a></li> <li><a class="reference internal" href="#drop-the-requirement-to-specify-the-location-of-an-sdist-and-or-wheels">Drop the requirement to specify the location of an sdist and/or wheels</a></li> <li><a class="reference internal" href="#drop-requiring-file-size-and-hashes">Drop requiring file size and hashes</a></li> <li><a class="reference internal" href="#drop-recording-the-sdist-file-name">Drop recording the sdist file name</a></li> <li><a class="reference internal" href="#make-packages-wheels-a-table">Make <code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code> a table</a></li> </ul> </li> <li><a class="reference internal" href="#self-referential">Self-Referential</a><ul> <li><a class="reference internal" href="#drop-the-tool-table">Drop the <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> table</a></li> <li><a class="reference internal" href="#list-the-requirement-inputs-for-the-file">List the requirement inputs for the file</a></li> </ul> </li> <li><a class="reference internal" href="#auditing">Auditing</a><ul> <li><a class="reference internal" href="#recording-dependents">Recording dependents</a></li> </ul> </li> </ul> </li> <li><a class="reference internal" href="#acknowledgements">Acknowledgements</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0751.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10