1528 lines
157 KiB
HTML
1528 lines
157 KiB
HTML
|
||
<!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 dependency specification 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 wh...">
|
||
<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 dependency specification 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 wh...">
|
||
<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> » </li>
|
||
<li><a href="../pep-0000/">PEP Index</a> » </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 <brett at python.org></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></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="#version"><code class="docutils literal notranslate"><span class="pre">version</span></code></a></li>
|
||
<li><a class="reference internal" href="#hash-algorithm"><code class="docutils literal notranslate"><span class="pre">hash-algorithm</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker"><code class="docutils literal notranslate"><span class="pre">[locker]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#locker-name"><code class="docutils literal notranslate"><span class="pre">locker.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-version"><code class="docutils literal notranslate"><span class="pre">locker.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-run"><code class="docutils literal notranslate"><span class="pre">locker.run</span></code></a><ul>
|
||
<li><a class="reference internal" href="#locker-run-module"><code class="docutils literal notranslate"><span class="pre">locker.run.module</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-run-args"><code class="docutils literal notranslate"><span class="pre">locker.run.args</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#groups"><code class="docutils literal notranslate"><span class="pre">[[groups]]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#groups-name"><code class="docutils literal notranslate"><span class="pre">groups.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-project"><code class="docutils literal notranslate"><span class="pre">groups.project</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements"><code class="docutils literal notranslate"><span class="pre">groups.requirements</span></code></a><ul>
|
||
<li><a class="reference internal" href="#groups-requirements-name"><code class="docutils literal notranslate"><span class="pre">groups.requirements.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-extras"><code class="docutils literal notranslate"><span class="pre">groups.requirements.extras</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-version"><code class="docutils literal notranslate"><span class="pre">groups.requirements.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-marker"><code class="docutils literal notranslate"><span class="pre">groups.requirements.marker</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</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-groups"><code class="docutils literal notranslate"><span class="pre">packages.groups</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-index-url"><code class="docutils literal notranslate"><span class="pre">packages.index-url</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-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><ul>
|
||
<li><a class="reference internal" href="#packages-dependencies-name"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-extras"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.extras</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-version"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-marker"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.marker</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-feature"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.feature</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#packages-editable"><code class="docutils literal notranslate"><span class="pre">packages.editable</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree"><code class="docutils literal notranslate"><span class="pre">[packages.source-tree]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#packages-source-tree-vcs"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.vcs</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-path"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.path</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-url"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.url</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-commit"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.commit</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-size"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-hash"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.hash</span></code></a></li>
|
||
</ul>
|
||
</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-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-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-size"><code class="docutils literal notranslate"><span class="pre">packages.sdist.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-sdist-hash"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hash</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-tags"><code class="docutils literal notranslate"><span class="pre">packages.wheels.tags</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-wheels-build"><code class="docutils literal notranslate"><span class="pre">packages.wheels.build</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-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-size"><code class="docutils literal notranslate"><span class="pre">packages.wheels.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-wheels-hash"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hash</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="#examples">Examples</a></li>
|
||
<li><a class="reference internal" href="#expectations-for-lockers">Expectations for Lockers</a></li>
|
||
<li><a class="reference internal" href="#expectations-for-installers">Expectations for Installers</a><ul>
|
||
<li><a class="reference internal" href="#pseudo-code">Pseudo-Code</a></li>
|
||
</ul>
|
||
</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="#a-flat-set-of-packages-to-install">A flat set of packages to install</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-specific-hash-algorithm-support">Requiring specific hash algorithm support</a></li>
|
||
<li><a class="reference internal" href="#require-a-url-or-file-path-for-files">Require a URL or file path for files</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="#multiple-hashes-per-file">Multiple hashes per 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">Recording the package indexes used</a></li>
|
||
<li><a class="reference internal" href="#locking-build-requirements-for-sdists">Locking build requirements for sdists</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
|
||
<li><a class="reference internal" href="#specify-requires-python-at-the-file-level">Specify <code class="docutils literal notranslate"><span class="pre">requires-python</span></code> at the file level?</a></li>
|
||
<li><a class="reference internal" href="#don-t-pre-parse-data">Don’t pre-parse data?</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#deferred-ideas">Deferred Ideas</a><ul>
|
||
<li><a class="reference internal" href="#per-file-locking">Per-file locking</a></li>
|
||
<li><a class="reference internal" href="#allowing-for-multiple-lock-files">Allowing for multiple lock files</a></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 dependency specification
|
||
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 (<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://github.com/astral-sh/uv">uv</a>, <a class="reference external" href="https://python-poetry.org/">Poetry</a>, and <a class="reference external" href="https://pypi.org/project/pdm/">PDM</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 and Poetry try to lock for <em>any</em> environment to some
|
||
degree. There’s also concerns around the lack of secure defaults in the face of
|
||
supply chain attacks (e.g., always 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. Rallying
|
||
around a single format removes that cost/barrier.</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 format is designed so that a <em>locker</em> which produces the lock file
|
||
and an <em>installer</em> which consumes the lock file can be separate tools. This
|
||
allows for situations such as cloud hosting providers to use their own installer
|
||
that’s optimized for their system which is independent of what locker the user
|
||
used to create their lock file.</p>
|
||
<p>The file format 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 installers and thus 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>Finally, the lock file is meant to be flexible enough to meets the various needs
|
||
tools have for choosing what to install. That means the lock file records the
|
||
dependency graph of what _may_ be installed. This allows tools to enter the
|
||
graph at any point and still have reproducible results from that root of the
|
||
graph. Flexibility also means supporting different installation scenarios within
|
||
the same lock file (e.g., with or without test dependencies).</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>. 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.</p>
|
||
<p>The lock file 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>All keys listed below are required unless otherwise noted. If two keys are
|
||
mutually exclusive to one another, then one of the keys is required while the
|
||
other is disallowed.</p>
|
||
<p>Keys in tables – including the top-level table – SHOULD be emitted by lockers
|
||
in the order they are listed in this PEP when applicable unless another sort
|
||
order is specified to minimize noise in diffs. If the keys are not explicitly
|
||
specified in this PEP, then the keys SHOULD be sorted by lexicographic order.</p>
|
||
<p>As well, lockers SHOULD sort arrays in lexicographic order unless otherwise
|
||
specified for the same reason.</p>
|
||
<section id="version">
|
||
<h4><a class="toc-backref" href="#version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">version</span></code></a></h4>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The version of the lock file format.</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">"1.0"</span></code>.</li>
|
||
<li>If an installer supports the major version but not the minor version, a tool
|
||
SHOULD warn when an unknown key is seen.</li>
|
||
<li>If an installer doesn’t support a major version, it MUST raise an error.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="hash-algorithm">
|
||
<h4><a class="toc-backref" href="#hash-algorithm" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">hash-algorithm</span></code></a></h4>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The name of the hash algorithm used for calculating all hash values.</li>
|
||
<li>Only a single hash algorithm is used for the entire file to allow hash values
|
||
to be written in inline tables for readability and compactness purposes by
|
||
only listing a single hash value instead of multiple values based on multiple
|
||
hash algorithms.</li>
|
||
<li>Specifying a single hash algorithm guarantees that an algorithm that the user
|
||
prefers is used consistently throughout the file without having to audit
|
||
each file hash value separately.</li>
|
||
<li>Allows for updating the entire file to a new hash algorithm without running
|
||
the risk of accidentally leaving an old hash value in the file.</li>
|
||
<li><a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#simple-repository-api-json" title="(in Python Packaging User Guide)"><span>JSON-based Simple API for Python Package Indexes</span></a> and the <code class="docutils literal notranslate"><span class="pre">hashes</span></code> dictionary of
|
||
of the <code class="docutils literal notranslate"><span class="pre">files</span></code> dictionary of the Project Details dictionary specifies what
|
||
values are valid and guidelines on what hash algorithms to use.</li>
|
||
<li>Failure to validate any hash values for any file that is to be installed MUST
|
||
raise an error.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="locker">
|
||
<h4><a class="toc-backref" href="#locker" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[locker]</span></code></a></h4>
|
||
<ul class="simple">
|
||
<li>Table</li>
|
||
<li>Record of the tool that generated the lock file.</li>
|
||
<li>Enough details SHOULD be provided such that the lock
|
||
file from the details in this table can be reproduced (provided the same I/O
|
||
data is available, e.g., Dependabot if only files from a repository is
|
||
necessary to run the command).</li>
|
||
</ul>
|
||
<section id="locker-name">
|
||
<h5><a class="toc-backref" href="#locker-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">locker.name</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The name of the tool used to create the lock file.</li>
|
||
<li>If the locker is a Python project, its normalized name SHOULD be used.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="locker-version">
|
||
<h5><a class="toc-backref" href="#locker-version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">locker.version</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The version of the tool used.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="locker-run">
|
||
<h5><a class="toc-backref" href="#locker-run" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">locker.run</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Inline table</li>
|
||
<li>Records the command used to create the lock file.</li>
|
||
</ul>
|
||
<section id="locker-run-module">
|
||
<h6><a class="toc-backref" href="#locker-run-module" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">locker.run.module</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>The module name used for running the locker (i.e. what would be passed to
|
||
<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span></code>).</li>
|
||
<li>Lockers MUST specify this key if the locker can be executed via <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span></code>.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="locker-run-args">
|
||
<h6><a class="toc-backref" href="#locker-run-args" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">locker.run.args</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Array of strings</li>
|
||
<li>If the locker has a CLI, the arguments to pass to the locker.</li>
|
||
<li>All paths MUST be relative to the lock file so that another tool could use
|
||
the lock file’s location as the current working directory.</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
</section>
|
||
<section id="groups">
|
||
<h4><a class="toc-backref" href="#groups" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[[groups]]</span></code></a></h4>
|
||
<ul class="simple">
|
||
<li>Array of tables</li>
|
||
<li>A named subset of packages as found in <code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code>.</li>
|
||
<li>Act as roots into the dependency graph.</li>
|
||
<li>Installers MUST allow the user to select one or more groups by name to
|
||
install all relevant packages together.</li>
|
||
<li>Installers SHOULD let the user skip specifying a name if there is only one
|
||
entry in the array.</li>
|
||
</ul>
|
||
<section id="groups-name">
|
||
<h5><a class="toc-backref" href="#groups-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.name</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The name of the group.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="groups-project">
|
||
<h5><a class="toc-backref" href="#groups-project" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.project</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">requirements</span></code></li>
|
||
<li>String</li>
|
||
<li>The normalized name of a package to act as the starting point into the
|
||
dependency graph.</li>
|
||
<li>Analogous to locking to the <code class="docutils literal notranslate"><span class="pre">[project]</span></code> table in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>.</li>
|
||
<li>Installers MUST let a user specify any optional features/extras that the
|
||
package provides.</li>
|
||
<li>Lockers MUST NOT allow for ambiguity by specifying multiple package versions
|
||
of the same package under the same group name when a package is listed in any
|
||
<code class="docutils literal notranslate"><span class="pre">project</span></code> key.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="groups-requirements">
|
||
<h5><a class="toc-backref" href="#groups-requirements" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.requirements</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">project</span></code></li>
|
||
<li>Array of tables</li>
|
||
<li>Represents the installation requirements for this group.</li>
|
||
<li>Analogous to a key in <code class="docutils literal notranslate"><span class="pre">[dependency-groups]</span></code> in <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>.</li>
|
||
<li>Lockers MUST make sure that resolving any requirement for any environment does
|
||
not lead to ambiguity by having multiple values in <code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code> match the
|
||
same requirement.</li>
|
||
<li>Values in the array SHOULD be written as inline tables, sorted
|
||
lexicographically by <code class="docutils literal notranslate"><span class="pre">name</span></code>, then by <code class="docutils literal notranslate"><span class="pre">feature</span></code> with the lack of that key
|
||
sorting first.</li>
|
||
</ul>
|
||
<section id="groups-requirements-name">
|
||
<h6><a class="toc-backref" href="#groups-requirements-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.requirements.name</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>Normalized name of the package.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="groups-requirements-extras">
|
||
<h6><a class="toc-backref" href="#groups-requirements-extras" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.requirements.extras</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Array of strings</li>
|
||
<li>The names of the extras specified for the requirement
|
||
(i.e. what comes between <code class="docutils literal notranslate"><span class="pre">[...]</span></code>).</li>
|
||
</ul>
|
||
</section>
|
||
<section id="groups-requirements-version">
|
||
<h6><a class="toc-backref" href="#groups-requirements-version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.requirements.version</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>The <a class="reference external" href="https://packaging.python.org/en/latest/specifications/version-specifiers/">version specifiers</a> for the requirement.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="groups-requirements-marker">
|
||
<h6><a class="toc-backref" href="#groups-requirements-marker" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">groups.requirements.marker</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>The <a class="reference external" href="https://packaging.python.org/en/latest/specifications/dependency-specifiers/#environment-markers">environment markers</a> for the requirement.</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
</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>Array of tables</li>
|
||
<li>The array contains all data on the nodes of the dependency graph.</li>
|
||
<li>Lockers SHOULD record packages in order by <code class="docutils literal notranslate"><span class="pre">name</span></code>
|
||
lexicographically, <code class="docutils literal notranslate"><span class="pre">version</span></code> by its Python <a class="reference external" href="https://packaging.python.org/en/latest/specifications/version-specifiers/">version specifiers</a>
|
||
ordering, and then by <code class="docutils literal notranslate"><span class="pre">groups</span></code> following Python’s sort order for lists of
|
||
strings (i.e. item by item, then by length as a tiebreaker).</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>String</li>
|
||
<li>The <a class="reference external" href="https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization">normalized name</a> of the package.</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>String</li>
|
||
<li>The version of the package.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-groups">
|
||
<h5><a class="toc-backref" href="#packages-groups" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.groups</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Array of strings</li>
|
||
<li>Associates this table with the <code class="docutils literal notranslate"><span class="pre">group.name</span></code> entries of the same names.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-index-url">
|
||
<h5><a class="toc-backref" href="#packages-index-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.index-url</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>Stores the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/#project-list">project index</a> URL from the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/simple-repository-api/">Simple Repository API</a>.</li>
|
||
<li>Useful for generating Packaging URLs (aka PURLs).</li>
|
||
<li>When possible, lockers SHOULD include this to assist with generating
|
||
<a class="reference external" href="https://www.cisa.gov/sbom">software bill of materials</a> (aka SBOMs).</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>Optional (defaults to <code class="docutils literal notranslate"><span class="pre">false</span></code>)</li>
|
||
<li>Boolean</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 reference</a>.</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>String</li>
|
||
<li>Holds the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/version-specifiers/">version specifiers</a> for Python version compatibility for the
|
||
package and version.</li>
|
||
<li>The value MUST match what’s provided by the package version, if available, via
|
||
<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>
|
||
</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>Array of tables</li>
|
||
<li>A record of the dependency requirements of the package and version.</li>
|
||
<li>The values MUST semantically match what’s provided by the package version via
|
||
<a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-requires-dist" title="(in Python Packaging User Guide)"><span>Requires-Dist (multiple use)</span></a> for all dependencies referenced
|
||
in the lock file (i.e all base dependencies plus all dependencies for extras
|
||
referenced in the lock file); lock files MAY list all dependencies for unused
|
||
extras if desired.</li>
|
||
<li>Values in the array SHOULD be written as inline tables, sorted
|
||
lexicographically by <code class="docutils literal notranslate"><span class="pre">name</span></code>, then by <code class="docutils literal notranslate"><span class="pre">feature</span></code> with the lack of that key
|
||
sorting first.</li>
|
||
</ul>
|
||
<section id="packages-dependencies-name">
|
||
<h6><a class="toc-backref" href="#packages-dependencies-name" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.name</span></code></a></h6>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">groups.requirements.name</span></code>.</p>
|
||
</section>
|
||
<section id="packages-dependencies-extras">
|
||
<h6><a class="toc-backref" href="#packages-dependencies-extras" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.extras</span></code></a></h6>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">groups.requirements.extras</span></code>.</p>
|
||
</section>
|
||
<section id="packages-dependencies-version">
|
||
<h6><a class="toc-backref" href="#packages-dependencies-version" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.version</span></code></a></h6>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">groups.requirements.version</span></code>.</p>
|
||
</section>
|
||
<section id="packages-dependencies-marker">
|
||
<h6><a class="toc-backref" href="#packages-dependencies-marker" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.marker</span></code></a></h6>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">groups.requirements.marker</span></code>.</p>
|
||
</section>
|
||
<section id="packages-dependencies-feature">
|
||
<h6><a class="toc-backref" href="#packages-dependencies-feature" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.feature</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>The optional feature/<a class="reference external" href="https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata-provides-extra" title="(in Python Packaging User Guide)"><span>Provides-Extra (multiple use)</span></a> that this
|
||
requirement is conditional on.</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="packages-editable">
|
||
<h5><a class="toc-backref" href="#packages-editable" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.editable</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Optional (defaults to <code class="docutils literal notranslate"><span class="pre">false</span></code>)</li>
|
||
<li>Boolean</li>
|
||
<li>Specifies whether the package should be installed in editable mode.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree">
|
||
<h5><a class="toc-backref" href="#packages-source-tree" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">[packages.source-tree]</span></code></a></h5>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Table</li>
|
||
<li>For recording where to find the <a class="reference external" href="https://packaging.python.org/en/latest/specifications/source-distribution-format/#source-trees">source tree</a> for the package version.</li>
|
||
<li>Lockers SHOULD write this table inline.</li>
|
||
<li>Support for source trees by installers is optional.</li>
|
||
<li>If support is provided by an installer it SHOULD be opt-in.</li>
|
||
<li>If multiple source trees are provided, installers MUST prefer either the
|
||
<code class="docutils literal notranslate"><span class="pre">vcs</span></code> option or a file for security/reproducibility due to their commit or
|
||
hash, respectively.</li>
|
||
</ul>
|
||
<section id="packages-source-tree-vcs">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-vcs" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.vcs</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>If specifying a VCS, the type of version control system used.</li>
|
||
<li>The valid values are specified by the
|
||
<a class="reference external" href="https://packaging.python.org/en/latest/specifications/direct-url-data-structure/#registered-vcs">registered VCSs</a>
|
||
of the direct URL data structure.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree-path">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-path" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.path</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Required if <code class="docutils literal notranslate"><span class="pre">url</span></code> is not set</li>
|
||
<li>String</li>
|
||
<li>A path to the source tree, which may be absolute or relative.</li>
|
||
<li>If the path is relative it MUST be relative to the lock file.</li>
|
||
<li>The path may either be to a directory, file archive, or VCS checkout if
|
||
<code class="docutils literal notranslate"><span class="pre">vcs</span></code> if is specified.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree-url">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-url" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.url</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Required if <code class="docutils literal notranslate"><span class="pre">path</span></code> is not set</li>
|
||
<li>String</li>
|
||
<li>A URL to a file archive containing the source tree, or a VCS checkout if
|
||
<code class="docutils literal notranslate"><span class="pre">vcs</span></code> is specified.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree-commit">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-commit" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.commit</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Required if <code class="docutils literal notranslate"><span class="pre">vcs</span></code> is set</li>
|
||
<li>String</li>
|
||
<li>The commit ID for the repository which represents the package and version.</li>
|
||
<li>The value MUST be immutable for the VCS for security purposes
|
||
(e.g. no Git tags).</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree-size">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-size" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.size</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Integer</li>
|
||
<li>The size in bytes for the source tree if it is a file.</li>
|
||
<li>Installers MUST verify the file size matches this value.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-source-tree-hash">
|
||
<h6><a class="toc-backref" href="#packages-source-tree-hash" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.hash</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Required if <code class="docutils literal notranslate"><span class="pre">url</span></code> or <code class="docutils literal notranslate"><span class="pre">path</span></code> points to a file</li>
|
||
<li>String</li>
|
||
<li>The hash value of the file contents using the hash algorithm specified by
|
||
<code class="docutils literal notranslate"><span class="pre">hash-algorithm</span></code>.</li>
|
||
<li>Installers MUST verify the hash matches the file.</li>
|
||
</ul>
|
||
</section>
|
||
</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>Optional</li>
|
||
<li>Table</li>
|
||
<li>The location of a source distribution as specified by
|
||
<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>Source distribution format</span></a>.</li>
|
||
<li>Lockers SHOULD write the table inline.</li>
|
||
<li>Support for source distributions by installers is optional.</li>
|
||
<li>If support is provided by an installer it SHOULD be opt-in.</li>
|
||
</ul>
|
||
<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>
|
||
<ul class="simple">
|
||
<li>Optional; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">path</span></code></li>
|
||
<li>String</li>
|
||
<li>The URL to the file.</li>
|
||
</ul>
|
||
</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>
|
||
<ul class="simple">
|
||
<li>Optional; mutually-exclusive with <code class="docutils literal notranslate"><span class="pre">url</span></code></li>
|
||
<li>String</li>
|
||
<li>A path to the file, which may be absolute or relative.</li>
|
||
<li>If the path is relative it MUST be relative to the lock 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>Optional and only applicable when <code class="docutils literal notranslate"><span class="pre">url</span></code> is specified</li>
|
||
<li>Offset date time</li>
|
||
<li>The upload date and time of the file as specified by a valid ISO 8601
|
||
date/time string for the <code class="docutils literal notranslate"><span class="pre">.files[]."upload-time"</span></code> field in the JSON
|
||
version of <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>
|
||
</ul>
|
||
</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>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>Integer</li>
|
||
<li>The size of the file in bytes.</li>
|
||
<li>Installers MUST verify the file size matches this value.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-sdist-hash">
|
||
<h6><a class="toc-backref" href="#packages-sdist-hash" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hash</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>String</li>
|
||
<li>The hash value of the file contents using the hash algorithm specified by
|
||
<code class="docutils literal notranslate"><span class="pre">hash-algorithm</span></code>.</li>
|
||
<li>Installers MUST verify the hash matches the file.</li>
|
||
</ul>
|
||
</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>Optional</li>
|
||
<li>Array of tables</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 version.</li>
|
||
<li>Lockers SHOULD write the table inline.</li>
|
||
<li>Lockers SHOULD sort the array values lexicographically by <code class="docutils literal notranslate"><span class="pre">tag</span></code>.</li>
|
||
</ul>
|
||
<section id="packages-wheels-tags">
|
||
<h6><a class="toc-backref" href="#packages-wheels-tags" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.tags</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Array of string</li>
|
||
<li>The uncompressed tag portion of the wheel file: Python, ABI, and platform.</li>
|
||
<li>Lockers MUST make sure the tag values are unique within the
|
||
<code class="docutils literal notranslate"><span class="pre">packages.wheels</span></code> array.</li>
|
||
</ul>
|
||
</section>
|
||
<section id="packages-wheels-build">
|
||
<h6><a class="toc-backref" href="#packages-wheels-build" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.build</span></code></a></h6>
|
||
<ul class="simple">
|
||
<li>Optional</li>
|
||
<li>String</li>
|
||
<li>The build tag for the wheel file (if appropriate).</li>
|
||
</ul>
|
||
</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.sdist.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.sdist.path</span></code>.</p>
|
||
</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-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.sdist.size</span></code>.</p>
|
||
</section>
|
||
<section id="packages-wheels-hash">
|
||
<h6><a class="toc-backref" href="#packages-wheels-hash" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hash</span></code></a></h6>
|
||
<p>See <code class="docutils literal notranslate"><span class="pre">packages.sdist.hash</span></code>.</p>
|
||
</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>Optional</li>
|
||
<li>Table</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-specification">pyproject.toml specification</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>Useful for scoping package version/release details (e.g., recording signing
|
||
identities to then use to verify package integrity separately from where the
|
||
package is hosted, prototyping future extensions to this file format, etc.).</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>Optional</li>
|
||
<li>Table</li>
|
||
<li>Same usage as that of the equivalent <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-specification">pyproject.toml specification</a>.</li>
|
||
</ul>
|
||
</section>
|
||
</section>
|
||
<section id="examples">
|
||
<h3><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h3>
|
||
<div class="highlight-TOML notranslate"><div class="highlight"><pre><span></span><span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'1.0'</span>
|
||
<span class="n">hash-algorithm</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'sha256'</span>
|
||
|
||
<span class="k">[locker]</span>
|
||
<span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'mousebender'</span>
|
||
<span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'pep'</span>
|
||
<span class="n">run</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">module</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mousebender'</span><span class="p">,</span><span class="w"> </span><span class="n">args</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'lock'</span><span class="p">,</span><span class="w"> </span><span class="s1">'--platform'</span><span class="p">,</span><span class="w"> </span><span class="s1">'cpython3.12-manylinux2014-x64'</span><span class="p">,</span><span class="w"> </span><span class="s1">'--platform'</span><span class="p">,</span><span class="w"> </span><span class="s1">'cpython3.12-windows-x64'</span><span class="p">,</span><span class="w"> </span><span class="s1">'cattrs'</span><span class="p">,</span><span class="w"> </span><span class="s1">'numpy'</span><span class="p">]</span><span class="w"> </span><span class="p">}</span>
|
||
|
||
<span class="k">[[groups]]</span>
|
||
<span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'Default'</span>
|
||
<span class="n">requirements</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="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cattrs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'numpy'</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="s1">'attrs'</span>
|
||
<span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'24.2.0'</span>
|
||
<span class="n">groups</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'Default'</span><span class="p">]</span>
|
||
<span class="n">index_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://pypi.org/simple/attrs'</span>
|
||
<span class="n">direct</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span>
|
||
<span class="n">requires_python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'>=3.7'</span>
|
||
<span class="n">dependencies</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="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'importlib-metadata'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'python_version < "3.8"'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cloudpickle'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'hypothesis'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mypy'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.11.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pympler'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-codspeed'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-mypy-plugins'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9" and python_version < "3.13"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-xdist'</span><span class="p">,</span><span class="w"> </span><span class="n">extras</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'psutil'</span><span class="p">],</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=4.3.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'benchmark'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cloudpickle'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'coverage'</span><span class="p">,</span><span class="w"> </span><span class="n">extras</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'toml'</span><span class="p">],</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=5.3'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'hypothesis'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mypy'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.11.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pympler'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-mypy-plugins'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9" and python_version < "3.13"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-xdist'</span><span class="p">,</span><span class="w"> </span><span class="n">extras</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'psutil'</span><span class="p">],</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=4.3.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cov'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cloudpickle'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'hypothesis'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mypy'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.11.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pre-commit'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pympler'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-mypy-plugins'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9" and python_version < "3.13"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-xdist'</span><span class="p">,</span><span class="w"> </span><span class="n">extras</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'psutil'</span><span class="p">],</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=4.3.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'dev'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cogapp'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'furo'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'myst-parser'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'sphinx'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'sphinx-notfound-page'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'sphinxcontrib-towncrier'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'towncrier'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'<24.7'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'docs'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cloudpickle'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'hypothesis'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mypy'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.11.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pympler'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-mypy-plugins'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9" and python_version < "3.13"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-xdist'</span><span class="p">,</span><span class="w"> </span><span class="n">extras</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'psutil'</span><span class="p">],</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=4.3.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'mypy'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.11.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests-mypy'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pytest-mypy-plugins'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'platform_python_implementation == "CPython" and python_version >= "3.9" and python_version < "3.13"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tests-mypy'</span><span class="w"> </span><span class="p">}</span>
|
||
<span class="p">]</span>
|
||
<span class="n">editable</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</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="w"> </span><span class="n">tags</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'py3-none-any'</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="s1">'https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl'</span><span class="p">,</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2'</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-08-06T14:37:36.958006+00:00</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">63001</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="s1">'cattrs'</span>
|
||
<span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'24.1.2'</span>
|
||
<span class="n">groups</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'Default'</span><span class="p">]</span>
|
||
<span class="n">index_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://pypi.org/simple/cattrs'</span>
|
||
<span class="n">direct</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span>
|
||
<span class="n">requires_python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'>=3.8'</span>
|
||
<span class="n">dependencies</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="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'attrs'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=23.1.0'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'exceptiongroup'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.1.1'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'python_version < "3.11"'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'typing-extensions'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'!=4.6.3,>=4.1.0'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'python_version < "3.11"'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pymongo'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=4.4.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'bson'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cbor2'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=5.4.6'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'cbor2'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'msgpack'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=1.0.5'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'msgpack'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'msgspec'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=0.18.5'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'implementation_name == "cpython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'msgspec'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'orjson'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=3.9.2'</span><span class="p">,</span><span class="w"> </span><span class="n">marker</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'implementation_name == "cpython"'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'orjson'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pyyaml'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=6.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'pyyaml'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tomlkit'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=0.11.8'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'tomlkit'</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'ujson'</span><span class="p">,</span><span class="w"> </span><span class="n">version</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'>=5.7.0'</span><span class="p">,</span><span class="w"> </span><span class="n">feature</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'ujson'</span><span class="w"> </span><span class="p">}</span>
|
||
<span class="p">]</span>
|
||
<span class="n">editable</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</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="w"> </span><span class="n">tags</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'py3-none-any'</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="s1">'https://files.pythonhosted.org/packages/c8/d5/867e75361fc45f6de75fe277dd085627a9db5ebb511a87f27dc1396b5351/cattrs-24.1.2-py3-none-any.whl'</span><span class="p">,</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0'</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-09-22T14:58:34.812643+00:00</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">66446</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="s1">'numpy'</span>
|
||
<span class="n">version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'2.1.2'</span>
|
||
<span class="n">groups</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'Default'</span><span class="p">]</span>
|
||
<span class="n">index_url</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'https://pypi.org/simple/numpy'</span>
|
||
<span class="n">direct</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span>
|
||
<span class="n">requires_python</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'>=3.10'</span>
|
||
<span class="n">dependencies</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
|
||
|
||
<span class="p">]</span>
|
||
<span class="n">editable</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</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="w"> </span><span class="n">tags</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'cp312-cp312-manylinux2014_x86_64'</span><span class="p">,</span><span class="w"> </span><span class="s1">'cp312-cp312-manylinux_2_17_x86_64'</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="s1">'https://files.pythonhosted.org/packages/9b/b4/e3c7e6fab0f77fff6194afa173d1f2342073d91b1d3b4b30b17c3fb4407a/numpy-2.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl'</span><span class="p">,</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'6d95f286b8244b3649b477ac066c6906fbb2905f8ac19b170e2175d3d799f4df'</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-10-05T18:36:20.729642+00:00</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">16041825</span><span class="w"> </span><span class="p">},</span>
|
||
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">tags</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="s1">'cp312-cp312-win_amd64'</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="s1">'https://files.pythonhosted.org/packages/4c/79/73735a6a5dad6059c085f240a4e74c9270feccd2bc66e4d31b5ca01d329c/numpy-2.1.2-cp312-cp312-win_amd64.whl'</span><span class="p">,</span><span class="w"> </span><span class="n">hash</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s1">'456e3b11cb79ac9946c822a56346ec80275eaf2950314b249b512896c0d2505e'</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-10-05T18:37:38.159022+00:00</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">12568254</span><span class="w"> </span><span class="p">}</span>
|
||
<span class="p">]</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="expectations-for-lockers">
|
||
<h3><a class="toc-backref" href="#expectations-for-lockers" role="doc-backlink">Expectations for Lockers</a></h3>
|
||
<ul class="simple">
|
||
<li>Lockers MUST make sure that entering the dependency graph via a specific group
|
||
will not lead to ambiguity for installers as to which value in
|
||
<code class="docutils literal notranslate"><span class="pre">[[packages]]</span></code> to install for any environment (this can be controlled for
|
||
via <code class="docutils literal notranslate"><span class="pre">packages.version</span></code> and <code class="docutils literal notranslate"><span class="pre">packages.groups</span></code>).</li>
|
||
<li>Lockers SHOULD try to make all logically related groups resolve together
|
||
(i.e. no ambiguity if grouped together).</li>
|
||
<li>If a <code class="docutils literal notranslate"><span class="pre">groups.project</span></code> would have extras that cause ambiguity or installation
|
||
failure due to conflicts between the extras, the locker MAY create
|
||
separate <code class="docutils literal notranslate"><span class="pre">groups.requirements</span></code> entries instead, otherwise the locker MUST
|
||
raise an error.</li>
|
||
<li>Lockers MAY try to lock for multiple environments in a single lock file.</li>
|
||
<li>Lockers MAY try to update a lock file containing <code class="docutils literal notranslate"><span class="pre">[tool]</span></code> and
|
||
<code class="docutils literal notranslate"><span class="pre">[packages.tool]</span></code> for other tools than themselves.</li>
|
||
<li>Lockers MAY want to provide a way to let users provide the information
|
||
necessary to lock for other environments, e.g., supporting a JSON
|
||
file format which specifies wheel tags and marker values.</li>
|
||
</ul>
|
||
<div class="highlight-JSON notranslate"><div class="highlight"><pre><span></span><span class="p">{</span>
|
||
<span class="w"> </span><span class="nt">"marker-values"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="nt">"<marker>"</span><span class="p">:</span><span class="w"> </span><span class="s2">"<value>"</span><span class="p">},</span>
|
||
<span class="w"> </span><span class="nt">"wheel-tags"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"<tag>"</span><span class="p">]</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
<section id="expectations-for-installers">
|
||
<h3><a class="toc-backref" href="#expectations-for-installers" role="doc-backlink">Expectations for Installers</a></h3>
|
||
<ul class="simple">
|
||
<li>Installers MAY support installation of non-binary files
|
||
(i.e. source trees and source distributions), but are not required to.</li>
|
||
<li>Installers MUST provide a way to avoid non-binary file installation for
|
||
reproducibility and security purposes.</li>
|
||
<li>Installers SHOULD make it opt-in to use non-binary file installation to
|
||
facilitate a secure-by-default approach.</li>
|
||
<li>If a traversal of the graph leads to any ambiguity as to what package version
|
||
to install (i.e. more than one package version qualifies), an error MUST be
|
||
raised.</li>
|
||
<li>Installers MUST only consider package versions included in any selected
|
||
groups (i.e. installers cannot consider packages outside of the groups
|
||
selected to install from).</li>
|
||
<li>Installers MUST error out if a package version lacks a way to install into the
|
||
chosen environment.</li>
|
||
<li>Installers MUST support installing into an empty environment.</li>
|
||
</ul>
|
||
<section id="pseudo-code">
|
||
<h4><a class="toc-backref" href="#pseudo-code" role="doc-backlink">Pseudo-Code</a></h4>
|
||
<div class="highlight-Python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">UnsatisfiableError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Raised when a requirement cannot be satisfied."""</span>
|
||
|
||
|
||
<span class="k">class</span> <span class="nc">AmbiguityError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Raised when a requirement has multiple solutions."""</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">install_packages</span><span class="p">(</span><span class="n">lock_file_contents</span><span class="p">):</span>
|
||
<span class="c1"># Hard-coded out of laziness.</span>
|
||
<span class="n">packages</span> <span class="o">=</span> <span class="n">choose_packages</span><span class="p">(</span><span class="n">lock_file_contents</span><span class="p">,</span> <span class="p">(</span><span class="n">GROUP_NAME</span><span class="p">,</span> <span class="nb">frozenset</span><span class="p">()))</span>
|
||
|
||
<span class="k">for</span> <span class="n">package</span> <span class="ow">in</span> <span class="n">packages</span><span class="p">:</span>
|
||
<span class="n">tags</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">packaging</span><span class="o">.</span><span class="n">tags</span><span class="o">.</span><span class="n">sys_tags</span><span class="p">())</span>
|
||
<span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">tags</span><span class="p">:</span> <span class="c1"># Prioritize by tag order.</span>
|
||
<span class="n">tag_str</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">tag</span><span class="p">)</span>
|
||
<span class="k">for</span> <span class="n">wheel</span> <span class="ow">in</span> <span class="n">package</span><span class="p">[</span><span class="s2">"wheels"</span><span class="p">]:</span>
|
||
<span class="k">if</span> <span class="n">tag_str</span> <span class="ow">in</span> <span class="n">wheel</span><span class="p">[</span><span class="s2">"tags"</span><span class="p">]:</span>
|
||
<span class="k">break</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">continue</span>
|
||
<span class="k">break</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">UnsatisfiableError</span><span class="p">(</span>
|
||
<span class="sa">f</span><span class="s2">"No wheel for </span><span class="si">{</span><span class="n">package</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">package</span><span class="p">[</span><span class="s1">'version'</span><span class="p">]</span><span class="si">}</span><span class="s2">"</span>
|
||
<span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Installing </span><span class="si">{</span><span class="n">package</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span><span class="si">}</span><span class="s2"> </span><span class="si">{</span><span class="n">package</span><span class="p">[</span><span class="s1">'version'</span><span class="p">]</span><span class="si">}</span><span class="s2"> (</span><span class="si">{</span><span class="n">tag_str</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">choose_packages</span><span class="p">(</span><span class="n">lock_file_data</span><span class="p">,</span> <span class="o">*</span><span class="n">selected_groups</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Select the package versions that should be installed based on the requested groups.</span>
|
||
|
||
<span class="sd"> 'selected_groups' is a sequence of two-item tuples, representing a group name and</span>
|
||
<span class="sd"> optionally any requested extras if the group is a project.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">group_names</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">(</span><span class="n">operator</span><span class="o">.</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">)(</span><span class="n">group</span><span class="p">)</span> <span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">selected_groups</span><span class="p">)</span>
|
||
<span class="n">available_packages</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># The packages in the selected groups.</span>
|
||
<span class="k">for</span> <span class="n">pkg</span> <span class="ow">in</span> <span class="n">lock_file_data</span><span class="p">[</span><span class="s2">"packages"</span><span class="p">]:</span>
|
||
<span class="k">if</span> <span class="nb">frozenset</span><span class="p">(</span><span class="n">pkg</span><span class="p">[</span><span class="s2">"groups"</span><span class="p">])</span> <span class="o">&</span> <span class="n">group_names</span><span class="p">:</span>
|
||
<span class="n">available_packages</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">pkg</span><span class="p">[</span><span class="s2">"name"</span><span class="p">],</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pkg</span><span class="p">)</span>
|
||
<span class="n">selected_packages</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># The package versions that have been selected.</span>
|
||
<span class="n">handled_extras</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1"># The extras that have been handled.</span>
|
||
<span class="n">requirements</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># A stack of requirements to satisfy.</span>
|
||
|
||
<span class="c1"># First, get our starting list of requirements.</span>
|
||
<span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">selected_groups</span><span class="p">:</span>
|
||
<span class="n">requirements</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">gather_requirements</span><span class="p">(</span><span class="n">lock_file_data</span><span class="p">,</span> <span class="n">group</span><span class="p">))</span>
|
||
|
||
<span class="c1"># Next, go through the requirements and try to find a **single** package version</span>
|
||
<span class="c1"># that satisfies each requirement.</span>
|
||
<span class="k">while</span> <span class="n">requirements</span><span class="p">:</span>
|
||
<span class="n">req</span> <span class="o">=</span> <span class="n">requirements</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||
<span class="c1"># Ignore requirements whose markers disqualify it.</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">applies_to_env</span><span class="p">(</span><span class="n">req</span><span class="p">):</span>
|
||
<span class="k">continue</span>
|
||
<span class="n">name</span> <span class="o">=</span> <span class="n">req</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]</span>
|
||
<span class="k">if</span> <span class="n">pkg</span> <span class="o">:=</span> <span class="n">selected_packages</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
|
||
<span class="c1"># Safety check that the cross-section of groups doesn't cause issues.</span>
|
||
<span class="c1"># It somewhat assumes the locker didn't mess up such that there would be</span>
|
||
<span class="c1"># ambiguity by what package version was initially selected.</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">version_satisfies</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">pkg</span><span class="p">):</span>
|
||
<span class="k">raise</span> <span class="n">UnsatisfiableError</span><span class="p">(</span>
|
||
<span class="sa">f</span><span class="s2">"requirement </span><span class="si">{</span><span class="n">req</span><span class="si">!r}</span><span class="s2"> not satisfied by "</span>
|
||
<span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">selected_packages</span><span class="p">[</span><span class="n">req</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]]</span><span class="si">!r}</span><span class="s2">"</span>
|
||
<span class="p">)</span>
|
||
<span class="k">if</span> <span class="s2">"extras"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">req</span><span class="p">:</span>
|
||
<span class="k">continue</span>
|
||
<span class="n">needed_extras</span> <span class="o">=</span> <span class="n">req</span><span class="p">[</span><span class="s2">"extras"</span><span class="p">]</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">extras</span> <span class="o">:=</span> <span class="n">handled_extras</span><span class="o">.</span><span class="n">set_default</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="nb">set</span><span class="p">()))</span><span class="o">.</span><span class="n">difference</span><span class="p">(</span>
|
||
<span class="n">needed_extras</span>
|
||
<span class="p">):</span>
|
||
<span class="k">continue</span>
|
||
<span class="c1"># This isn't optimal as we may tread over the same extras multiple times,</span>
|
||
<span class="c1"># but eventually the maximum set of extras for the package will be handled</span>
|
||
<span class="c1"># and thus the above guard will short-circuit adding any more requirements.</span>
|
||
<span class="n">extras</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">needed_extras</span><span class="p">)</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="c1"># Raises UnsatisfiableError or AmbiguityError if no suitable, single package</span>
|
||
<span class="c1"># version is found.</span>
|
||
<span class="n">pkg</span> <span class="o">=</span> <span class="n">compatible_package_version</span><span class="p">(</span><span class="n">req</span><span class="p">,</span> <span class="n">available_packages</span><span class="p">[</span><span class="n">req</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]])</span>
|
||
<span class="n">selected_packages</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">pkg</span>
|
||
<span class="n">requirements</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">dependencies</span><span class="p">(</span><span class="n">pkg</span><span class="p">,</span> <span class="n">req</span><span class="p">))</span>
|
||
|
||
<span class="k">return</span> <span class="n">selected_packages</span><span class="o">.</span><span class="n">values</span><span class="p">()</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">gather_requirements</span><span class="p">(</span><span class="n">locked_file_data</span><span class="p">,</span> <span class="n">group</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Return a collection of all requirements for a group."""</span>
|
||
<span class="c1"># Hard-coded to support `groups.requirements` out of laziness.</span>
|
||
<span class="n">group_name</span><span class="p">,</span> <span class="n">_extras</span> <span class="o">=</span> <span class="n">group</span>
|
||
<span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">locked_file_data</span><span class="p">[</span><span class="s2">"groups"</span><span class="p">]:</span>
|
||
<span class="k">if</span> <span class="n">group</span><span class="p">[</span><span class="s2">"name"</span><span class="p">]</span> <span class="o">==</span> <span class="n">group_name</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">group</span><span class="p">[</span><span class="s2">"requirements"</span><span class="p">]</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Group </span><span class="si">{</span><span class="n">group_name</span><span class="si">!r}</span><span class="s2"> not found in lock file"</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">applies_to_env</span><span class="p">(</span><span class="n">requirement</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Check if the requirement applies to the current environment."""</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">markers</span> <span class="o">=</span> <span class="n">requirement</span><span class="p">[</span><span class="s2">"marker"</span><span class="p">]</span>
|
||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="kc">True</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="n">packaging</span><span class="o">.</span><span class="n">markers</span><span class="o">.</span><span class="n">Marker</span><span class="p">(</span><span class="n">markers</span><span class="p">)</span><span class="o">.</span><span class="n">evaluate</span><span class="p">()</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">version_satisfies</span><span class="p">(</span><span class="n">requirement</span><span class="p">,</span> <span class="n">package</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Check if the package version satisfies the requirement."""</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">raw_specifier</span> <span class="o">=</span> <span class="n">requirement</span><span class="p">[</span><span class="s2">"version"</span><span class="p">]</span>
|
||
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
||
<span class="k">return</span> <span class="kc">True</span>
|
||
<span class="k">else</span><span class="p">:</span>
|
||
<span class="n">specifier</span> <span class="o">=</span> <span class="n">packaging</span><span class="o">.</span><span class="n">specifiers</span><span class="o">.</span><span class="n">SpecifierSet</span><span class="p">(</span><span class="n">raw_specifier</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">specifier</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="n">package</span><span class="p">[</span><span class="s2">"version"</span><span class="p">],</span> <span class="n">prereleases</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">compatible_package_version</span><span class="p">(</span><span class="n">requirement</span><span class="p">,</span> <span class="n">available_packages</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Return the package version that satisfies the requirement.</span>
|
||
|
||
<span class="sd"> If no package version can satisfy the requirement, raise UnsatisfiableError. If</span>
|
||
<span class="sd"> multiple package versions can satisfy the requirement, raise AmbiguityError.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">possible_packages</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="n">pkg</span> <span class="k">for</span> <span class="n">pkg</span> <span class="ow">in</span> <span class="n">available_packages</span> <span class="k">if</span> <span class="n">version_satisfies</span><span class="p">(</span><span class="n">requirement</span><span class="p">,</span> <span class="n">pkg</span><span class="p">)</span>
|
||
<span class="p">]</span>
|
||
<span class="k">if</span> <span class="ow">not</span> <span class="n">possible_packages</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">UnsatisfiableError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No package version satisfies </span><span class="si">{</span><span class="n">requirement</span><span class="si">!r}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">possible_packages</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
||
<span class="k">raise</span> <span class="n">AmbiguityError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Multiple package versions satisfy </span><span class="si">{</span><span class="n">requirement</span><span class="si">!r}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">possible_packages</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
|
||
|
||
<span class="k">def</span> <span class="nf">dependencies</span><span class="p">(</span><span class="n">package</span><span class="p">,</span> <span class="n">requirement</span><span class="p">):</span>
|
||
<span class="w"> </span><span class="sd">"""Return the dependencies of the package.</span>
|
||
|
||
<span class="sd"> The extras from the requirement will extend the base requirements as needed.</span>
|
||
<span class="sd"> """</span>
|
||
<span class="n">applicable_deps</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="n">extras</span> <span class="o">=</span> <span class="nb">frozenset</span><span class="p">(</span><span class="n">requirement</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"extras"</span><span class="p">,</span> <span class="p">[]))</span>
|
||
<span class="k">for</span> <span class="n">dep</span> <span class="ow">in</span> <span class="n">package</span><span class="p">[</span><span class="s2">"dependencies"</span><span class="p">]:</span>
|
||
<span class="k">if</span> <span class="s2">"feature"</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dep</span> <span class="ow">or</span> <span class="n">dep</span><span class="p">[</span><span class="s2">"feature"</span><span class="p">]</span> <span class="ow">in</span> <span class="n">extras</span><span class="p">:</span>
|
||
<span class="n">applicable_deps</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">dep</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">applicable_deps</span>
|
||
</pre></div>
|
||
</div>
|
||
</section>
|
||
</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. For tools
|
||
that don’t document their lock file format, they could choose to simply start
|
||
using the format internally and then transition to saving their lock files with
|
||
a name supported by this PEP. For tools with a preexisting, documented format,
|
||
they could provide an option to choose which format to emit.</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 that 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 an 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.
|
||
Lockers 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, that
|
||
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 (and should be) installed.</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 wheels can be found at
|
||
<a class="reference external" href="https://github.com/brettcannon/mousebender/tree/pep">https://github.com/brettcannon/mousebender/tree/pep</a> .</p>
|
||
</section>
|
||
<section id="rejected-ideas">
|
||
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
|
||
<section id="a-flat-set-of-packages-to-install">
|
||
<h3><a class="toc-backref" href="#a-flat-set-of-packages-to-install" role="doc-backlink">A flat set of packages to install</a></h3>
|
||
<p>An earlier version of this PEP proposed to use a flat set of package versions
|
||
instead of a graph. The idea was that each package version could be evaluated in
|
||
isolation as to whether it applied to an environment for installation. The hope
|
||
was that would lend itself to easier auditing as one wouldn’t have to worry
|
||
about how a package version fit into the graph when looking at e.g., a diff for
|
||
a lock file.</p>
|
||
<p>Unfortunately this was deemed not as flexible as using a graph. For instance,
|
||
recording the graph
|
||
<a class="reference external" href="https://discuss.python.org/t/pep-751-lock-files-again/59173/327">assists in dependency analysis for tools like GitHub</a>.
|
||
A graph also makes following how you ended up with dependencies within your lock
|
||
file from any point in the graph. It also balances out the implementation costs
|
||
a bit more between lockers and installers by alleviating the complexity off of
|
||
lockers a bit for only a minor increase in complexity for installers by
|
||
involving standard graph-traversing algorithms instead of a linear walk.</p>
|
||
<p>And if the dependency graph is already being recorded for the above benefits,
|
||
then recording that same data in a flattened manner is redundant that makes
|
||
lock files larger and potentially more unruly.</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 packages. 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-specific-hash-algorithm-support">
|
||
<h3><a class="toc-backref" href="#requiring-specific-hash-algorithm-support" role="doc-backlink">Requiring specific 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="require-a-url-or-file-path-for-files">
|
||
<h3><a class="toc-backref" href="#require-a-url-or-file-path-for-files" role="doc-backlink">Require a URL or file path for files</a></h3>
|
||
<p>Originally references to files were required, e.g., <code class="docutils literal notranslate"><span class="pre">packages.sdist.url</span></code> or
|
||
<code class="docutils literal notranslate"><span class="pre">packages.sdist.path</span></code>. But at least
|
||
<a class="reference external" href="https://discuss.python.org/t/pep-751-now-with-graphs/69721/34">one use-case</a>
|
||
surfaced during discussions about this PEP where statically specifying the
|
||
location of files would be problematic. And in earlier discussions the idea of
|
||
the location being a hint wasn’t preferred. Hence the PEP now makes the data
|
||
optional, but considers the locations accurate if specified.</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="multiple-hashes-per-file">
|
||
<h4><a class="toc-backref" href="#multiple-hashes-per-file" role="doc-backlink">Multiple hashes per file</a></h4>
|
||
<p>An initial version of this PEP proposed supporting multiple hashes per file. The
|
||
idea was to allow one to choose which hashing algorithm they wanted to go with
|
||
when installing. But upon reflection it seemed like an unnecessary complication
|
||
as there was no guarantee the hashes provided would satisfy the user’s needs.
|
||
As well, if the single hash algorithm used in the lock file wasn’t sufficient,
|
||
rehashing the files involved as a way to migrate to a different algorithm didn’t
|
||
seem insurmountable.</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">
|
||
<h4><a class="toc-backref" href="#recording-the-package-indexes-used" role="doc-backlink">Recording the package indexes used</a></h4>
|
||
<p>Recording what package indexes were used by the locker to decide what to lock
|
||
for 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>
|
||
</section>
|
||
<section id="open-issues">
|
||
<h2><a class="toc-backref" href="#open-issues" role="doc-backlink">Open Issues</a></h2>
|
||
<section id="specify-requires-python-at-the-file-level">
|
||
<h3><a class="toc-backref" href="#specify-requires-python-at-the-file-level" role="doc-backlink">Specify <code class="docutils literal notranslate"><span class="pre">requires-python</span></code> at the file level?</a></h3>
|
||
<p>The lock file formats from <a class="reference external" href="https://pypi.org/project/pdm/">PDM</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> all specify
|
||
<code class="docutils literal notranslate"><span class="pre">requires-python</span></code> at the top level for the absolute minimum Python version
|
||
needed for the lock file. This can be inferred, though, by examining all
|
||
<code class="docutils literal notranslate"><span class="pre">packages.requires-python</span></code> values. The global value might also not be
|
||
accurate for all platforms depending on how environment markers influence what
|
||
package versions are installed and what their Python version requirements are.</p>
|
||
</section>
|
||
<section id="don-t-pre-parse-data">
|
||
<h3><a class="toc-backref" href="#don-t-pre-parse-data" role="doc-backlink">Don’t pre-parse data?</a></h3>
|
||
<p>This PEP currently takes the viewpoint that if a piece of data is going to be
|
||
parsed by installers everytime they run, then trying to pre-parse as much as
|
||
possible so the TOML parser can help is a good thing. The thinking is TOML
|
||
parsers have a higher chance of being optimized, and so letting them do more
|
||
parsing leads to a faster outcome. It should also increase readability by
|
||
breaking apart data upfront more.</p>
|
||
<p>But in the case of doing this to wheel file names, some might consider it too
|
||
much. The question becomes whether separating out all the parts of a wheel
|
||
file name hinders readability because people are used to reading the file names
|
||
already, or by clearly separating its parts it actually helps make installers
|
||
faster, easier to write, and doesn’t hinder readability.</p>
|
||
<p>This all equally applies to requirement specifiers.</p>
|
||
</section>
|
||
</section>
|
||
<section id="deferred-ideas">
|
||
<h2><a class="toc-backref" href="#deferred-ideas" role="doc-backlink">Deferred Ideas</a></h2>
|
||
<section id="per-file-locking">
|
||
<h3><a class="toc-backref" href="#per-file-locking" role="doc-backlink">Per-file locking</a></h3>
|
||
<p>An earlier version of this PEP supported two approaches to locking: <em>per-file</em>
|
||
and <strong>per-package</strong>. The idea for the former approach to locking was that if you
|
||
were locking for an a-priori set of environments you could lock to just the
|
||
files necessary to install into those environments. The thinking was that by
|
||
only listing a subset of files that auditing would be easier.</p>
|
||
<p>Unfortunately there was disagreement on how best to express upfront what the
|
||
supported environment requirements would be. Since what this PEP currently
|
||
proposes still prevents accidental success of installation into unsupported
|
||
environments, this idea has been deferred until such time someone can come up
|
||
with a representation that makes sense.</p>
|
||
</section>
|
||
<section id="allowing-for-multiple-lock-files">
|
||
<h3><a class="toc-backref" href="#allowing-for-multiple-lock-files" role="doc-backlink">Allowing for multiple lock files</a></h3>
|
||
<p>Before the introduction of <code class="docutils literal notranslate"><span class="pre">[[groups]]</span></code>, this PEP proposed supporting multiple
|
||
lock files that would match the regular expression
|
||
<code class="docutils literal notranslate"><span class="pre">r"pylock\.(.+)\.toml"</span></code> if a name for the lock file is desired or if multiple
|
||
lock files exist. But since <code class="docutils literal notranslate"><span class="pre">[[groups]]</span></code> subsumes a lot of the need to support
|
||
multiple lock files, this specific feature can be postponed until such time that
|
||
a need is shown to support multiple lock files.</p>
|
||
</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.</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">2024-11-05 19:18:47 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="#version"><code class="docutils literal notranslate"><span class="pre">version</span></code></a></li>
|
||
<li><a class="reference internal" href="#hash-algorithm"><code class="docutils literal notranslate"><span class="pre">hash-algorithm</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker"><code class="docutils literal notranslate"><span class="pre">[locker]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#locker-name"><code class="docutils literal notranslate"><span class="pre">locker.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-version"><code class="docutils literal notranslate"><span class="pre">locker.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-run"><code class="docutils literal notranslate"><span class="pre">locker.run</span></code></a><ul>
|
||
<li><a class="reference internal" href="#locker-run-module"><code class="docutils literal notranslate"><span class="pre">locker.run.module</span></code></a></li>
|
||
<li><a class="reference internal" href="#locker-run-args"><code class="docutils literal notranslate"><span class="pre">locker.run.args</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#groups"><code class="docutils literal notranslate"><span class="pre">[[groups]]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#groups-name"><code class="docutils literal notranslate"><span class="pre">groups.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-project"><code class="docutils literal notranslate"><span class="pre">groups.project</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements"><code class="docutils literal notranslate"><span class="pre">groups.requirements</span></code></a><ul>
|
||
<li><a class="reference internal" href="#groups-requirements-name"><code class="docutils literal notranslate"><span class="pre">groups.requirements.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-extras"><code class="docutils literal notranslate"><span class="pre">groups.requirements.extras</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-version"><code class="docutils literal notranslate"><span class="pre">groups.requirements.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#groups-requirements-marker"><code class="docutils literal notranslate"><span class="pre">groups.requirements.marker</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</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-groups"><code class="docutils literal notranslate"><span class="pre">packages.groups</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-index-url"><code class="docutils literal notranslate"><span class="pre">packages.index-url</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-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><ul>
|
||
<li><a class="reference internal" href="#packages-dependencies-name"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.name</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-extras"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.extras</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-version"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.version</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-marker"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.marker</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-dependencies-feature"><code class="docutils literal notranslate"><span class="pre">packages.dependencies.feature</span></code></a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#packages-editable"><code class="docutils literal notranslate"><span class="pre">packages.editable</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree"><code class="docutils literal notranslate"><span class="pre">[packages.source-tree]</span></code></a><ul>
|
||
<li><a class="reference internal" href="#packages-source-tree-vcs"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.vcs</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-path"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.path</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-url"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.url</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-commit"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.commit</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-size"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-source-tree-hash"><code class="docutils literal notranslate"><span class="pre">packages.source-tree.hash</span></code></a></li>
|
||
</ul>
|
||
</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-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-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-size"><code class="docutils literal notranslate"><span class="pre">packages.sdist.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-sdist-hash"><code class="docutils literal notranslate"><span class="pre">packages.sdist.hash</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-tags"><code class="docutils literal notranslate"><span class="pre">packages.wheels.tags</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-wheels-build"><code class="docutils literal notranslate"><span class="pre">packages.wheels.build</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-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-size"><code class="docutils literal notranslate"><span class="pre">packages.wheels.size</span></code></a></li>
|
||
<li><a class="reference internal" href="#packages-wheels-hash"><code class="docutils literal notranslate"><span class="pre">packages.wheels.hash</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="#examples">Examples</a></li>
|
||
<li><a class="reference internal" href="#expectations-for-lockers">Expectations for Lockers</a></li>
|
||
<li><a class="reference internal" href="#expectations-for-installers">Expectations for Installers</a><ul>
|
||
<li><a class="reference internal" href="#pseudo-code">Pseudo-Code</a></li>
|
||
</ul>
|
||
</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="#a-flat-set-of-packages-to-install">A flat set of packages to install</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-specific-hash-algorithm-support">Requiring specific hash algorithm support</a></li>
|
||
<li><a class="reference internal" href="#require-a-url-or-file-path-for-files">Require a URL or file path for files</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="#multiple-hashes-per-file">Multiple hashes per 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">Recording the package indexes used</a></li>
|
||
<li><a class="reference internal" href="#locking-build-requirements-for-sdists">Locking build requirements for sdists</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
|
||
<li><a class="reference internal" href="#specify-requires-python-at-the-file-level">Specify <code class="docutils literal notranslate"><span class="pre">requires-python</span></code> at the file level?</a></li>
|
||
<li><a class="reference internal" href="#don-t-pre-parse-data">Don’t pre-parse data?</a></li>
|
||
</ul>
|
||
</li>
|
||
<li><a class="reference internal" href="#deferred-ideas">Deferred Ideas</a><ul>
|
||
<li><a class="reference internal" href="#per-file-locking">Per-file locking</a></li>
|
||
<li><a class="reference internal" href="#allowing-for-multiple-lock-files">Allowing for multiple lock files</a></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> |