python-peps/pep-0496/index.html

268 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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 496 Environment Markers | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0496/">
<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 496 Environment Markers | peps.python.org'>
<meta property="og:description" content="An environment marker describes a condition about the current execution environment. They are used to indicate when certain dependencies are only required in particular environments, and to indicate supported platforms for distributions with additional ...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0496/">
<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="An environment marker describes a condition about the current execution environment. They are used to indicate when certain dependencies are only required in particular environments, and to indicate supported platforms for distributions with additional ...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 496</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 496 Environment Markers</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">James Polley &lt;jp&#32;&#97;t&#32;jamezpolley.com&gt;</dd>
<dt class="field-even">BDFL-Delegate<span class="colon">:</span></dt>
<dd class="field-even">Alyssa Coghlan &lt;ncoghlan&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-odd">Status<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Formally declined and will not be accepted">Rejected</abbr></dd>
<dt class="field-even">Type<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">Informational</abbr></dd>
<dt class="field-odd">Topic<span class="colon">:</span></dt>
<dd class="field-odd"><a class="reference external" href="../topic/packaging/">Packaging</a></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">03-Jul-2015</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#pep-status">PEP Status</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#micro-language">Micro-language</a><ul>
<li><a class="reference internal" href="#strings">Strings</a></li>
<li><a class="reference internal" href="#version-numbers">Version numbers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="pep-status">
<h2><a class="toc-backref" href="#pep-status" role="doc-backlink">PEP Status</a></h2>
<p>After this PEP was initially drafted, <a class="pep reference internal" href="../pep-0508/" title="PEP 508 Dependency specification for Python Software Packages">PEP 508</a> was developed and submitted to
fully specify the dependency declaration syntax, including environment markers.
As a result, this PEP ended up being rejected in favour of the more comprehensive
<a class="pep reference internal" href="../pep-0508/" title="PEP 508 Dependency specification for Python Software Packages">PEP 508</a>.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>An <strong>environment marker</strong> describes a condition about the current execution
environment. They are used to indicate when certain dependencies are only
required in particular environments, and to indicate supported platforms
for distributions with additional constraints beyond the availability of a
Python runtime.</p>
<p>Environment markers were first specified in <a class="pep reference internal" href="../pep-0345/" title="PEP 345 Metadata for Python Software Packages 1.2">PEP 345</a>. <a class="pep reference internal" href="../pep-0426/" title="PEP 426 Metadata for Python Software Packages 2.0">PEP 426</a>
(which would replace <a class="pep reference internal" href="../pep-0345/" title="PEP 345 Metadata for Python Software Packages 1.2">PEP 345</a>) proposed extensions to the markers.
When 2.7.10 was released, even these extensions became insufficient due to
their reliance on simple lexical comparisons, and thus this PEP has been born.</p>
</section>
<section id="rationale">
<h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2>
<p>Many Python packages are written with portability in mind.</p>
<p>For many packages this means they aim to support a wide range of
Python releases. If they depend on libraries such as <code class="docutils literal notranslate"><span class="pre">argparse</span></code> -
which started as external libraries, but later got incorporated into
core - specifying a single set of requirements is difficult, as the
set of required packages differs depending on the version of Python in
use.</p>
<p>For other packages, designing for portability means supporting
multiple operating systems. However, the significant differences
between them may mean that particular dependencies are only needed on
particular platforms (relying on <code class="docutils literal notranslate"><span class="pre">pywin32</span></code> only on Windows, for
example)”</p>
<p>Environment Markers attempt to provide more flexibility in a list of
requirements by allowing the developer to list requirements that are
specific to a particular environment.</p>
</section>
<section id="examples">
<h2><a class="toc-backref" href="#examples" role="doc-backlink">Examples</a></h2>
<p>Here are some examples of such markers inside a requirements.txt:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pywin32</span> <span class="o">&gt;=</span><span class="mf">1.0</span> <span class="p">;</span> <span class="n">sys_platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span>
<span class="n">unittest2</span> <span class="o">&gt;=</span><span class="mf">2.0</span><span class="p">,</span><span class="o">&lt;</span><span class="mf">3.0</span> <span class="p">;</span> <span class="n">python_version</span> <span class="o">==</span> <span class="s1">&#39;2.4&#39;</span> <span class="ow">or</span> <span class="n">python_version</span> <span class="o">==</span> <span class="s1">&#39;2.5&#39;</span>
<span class="n">backports</span><span class="o">.</span><span class="n">ssl_match_hostname</span> <span class="o">&gt;=</span> <span class="mf">3.4</span> <span class="p">;</span> <span class="n">python_version</span> <span class="o">&lt;</span> <span class="s1">&#39;2.7.9&#39;</span> <span class="ow">or</span> <span class="p">(</span><span class="n">python_version</span> <span class="o">&gt;=</span> <span class="s1">&#39;3.0&#39;</span> <span class="ow">and</span> <span class="n">python_version</span> <span class="o">&lt;</span> <span class="s1">&#39;3.4&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>And heres an example of some conditional metadata included in
setup.py for a distribution that requires PyWin32 both at runtime and
buildtime when using Windows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">setup</span><span class="p">(</span>
<span class="n">install_requires</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;pywin32 &gt; 1.0 : sys.platform == &#39;win32&#39;&quot;</span><span class="p">],</span>
<span class="n">setup_requires</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;pywin32 &gt; 1.0 : sys.platform == &#39;win32&#39;&quot;</span><span class="p">]</span>
<span class="p">)</span>
</pre></div>
</div>
</section>
<section id="micro-language">
<h2><a class="toc-backref" href="#micro-language" role="doc-backlink">Micro-language</a></h2>
<p>The micro-language behind this is as follows. It compares:</p>
<ul class="simple">
<li>strings with the <code class="docutils literal notranslate"><span class="pre">==</span></code> and <code class="docutils literal notranslate"><span class="pre">in</span></code> operators (and their opposites)</li>
<li>version numbers with the <code class="docutils literal notranslate"><span class="pre">&lt;</span></code>, <code class="docutils literal notranslate"><span class="pre">&lt;=</span></code>, <code class="docutils literal notranslate"><span class="pre">&gt;=</span></code>, and <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> operators
in addition to those supported for strings</li>
</ul>
<p>The usual boolean operators <code class="docutils literal notranslate"><span class="pre">and</span></code> and <code class="docutils literal notranslate"><span class="pre">or</span></code> can be used to combine
expressions, and parentheses are supported for grouping.</p>
<p>The pseudo-grammar is</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MARKER</span><span class="p">:</span> <span class="n">EXPR</span> <span class="p">[(</span><span class="ow">and</span><span class="o">|</span><span class="ow">or</span><span class="p">)</span> <span class="n">EXPR</span><span class="p">]</span><span class="o">*</span>
<span class="n">EXPR</span><span class="p">:</span> <span class="p">(</span><span class="s2">&quot;(&quot;</span> <span class="n">MARKER</span> <span class="s2">&quot;)&quot;</span><span class="p">)</span> <span class="o">|</span> <span class="p">(</span><span class="n">STREXPR</span><span class="o">|</span><span class="n">VEREXPR</span><span class="p">)</span>
<span class="n">STREXPR</span><span class="p">:</span> <span class="n">STRING</span> <span class="p">[</span><span class="n">STRCMPOP</span> <span class="n">STREXPR</span><span class="p">]</span>
<span class="n">STRCMPOP</span><span class="p">:</span> <span class="o">==|!=|</span><span class="ow">in</span><span class="o">|</span><span class="ow">not</span> <span class="ow">in</span>
<span class="n">VEREXPR</span><span class="p">:</span> <span class="n">VERSION</span> <span class="p">[</span><span class="n">VERCMPOP</span> <span class="n">VEREXPR</span><span class="p">]</span>
<span class="n">VERCMPOP</span><span class="p">:</span> <span class="p">(</span><span class="o">==|!=|&lt;|&gt;|&lt;=|&gt;=</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">SUBEXPR</span></code> is either a Python string (such as <code class="docutils literal notranslate"><span class="pre">'win32'</span></code>) or one of
the <code class="docutils literal notranslate"><span class="pre">Strings</span></code> marker variables listed below.</p>
<p><code class="docutils literal notranslate"><span class="pre">VEREXPR</span></code> is a <a class="pep reference internal" href="../pep-0440/" title="PEP 440 Version Identification and Dependency Specification">PEP 440</a> version identifier, or one of the
<code class="docutils literal notranslate"><span class="pre">Version</span> <span class="pre">number</span></code> marker variables listed below. Comparisons between
version numbers are done using <a class="pep reference internal" href="../pep-0440/" title="PEP 440 Version Identification and Dependency Specification">PEP 440</a> semantics.</p>
<section id="strings">
<h3><a class="toc-backref" href="#strings" role="doc-backlink">Strings</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">os_name</span></code>: <code class="docutils literal notranslate"><span class="pre">os.name</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">sys_platform</span></code>: <code class="docutils literal notranslate"><span class="pre">sys.platform</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">platform_release</span></code>: <code class="docutils literal notranslate"><span class="pre">platform.release()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">implementation_name</span></code>: <code class="docutils literal notranslate"><span class="pre">sys.implementation.name</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">platform_machine</span></code>: <code class="docutils literal notranslate"><span class="pre">platform.machine()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">platform_python_implementation</span></code>: <code class="docutils literal notranslate"><span class="pre">platform.python_implementation()</span></code></li>
</ul>
<p>If a particular string value is not available (such as <code class="docutils literal notranslate"><span class="pre">sys.implementation.name</span></code>
in versions of Python prior to 3.3), the corresponding marker
variable MUST be considered equivalent to the empty string.</p>
<p>If a particular version number value is not available (such as
<code class="docutils literal notranslate"><span class="pre">sys.implementation.version</span></code> in versions of Python prior to 3.3) the
corresponding marker variable MUST be considered equivalent to <code class="docutils literal notranslate"><span class="pre">0</span></code></p>
</section>
<section id="version-numbers">
<h3><a class="toc-backref" href="#version-numbers" role="doc-backlink">Version numbers</a></h3>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">python_version</span></code>: <code class="docutils literal notranslate"><span class="pre">platform.python_version()[:3]</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">python_full_version</span></code>: see definition below</li>
<li><code class="docutils literal notranslate"><span class="pre">platform_version</span></code>: <code class="docutils literal notranslate"><span class="pre">platform.version()</span></code></li>
<li><code class="docutils literal notranslate"><span class="pre">implementation_version</span></code>: see definition below</li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">python_full_version</span></code> and <code class="docutils literal notranslate"><span class="pre">implementation_version</span></code> marker variables
are derived from <code class="docutils literal notranslate"><span class="pre">sys.version_info</span></code> and <code class="docutils literal notranslate"><span class="pre">sys.implementation.version</span></code>
respectively, in accordance with the following algorithm:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">format_full_version</span><span class="p">(</span><span class="n">info</span><span class="p">):</span>
<span class="n">version</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="si">{0.major}</span><span class="s1">.</span><span class="si">{0.minor}</span><span class="s1">.</span><span class="si">{0.micro}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">info</span><span class="p">)</span>
<span class="n">kind</span> <span class="o">=</span> <span class="n">info</span><span class="o">.</span><span class="n">releaselevel</span>
<span class="k">if</span> <span class="n">kind</span> <span class="o">!=</span> <span class="s1">&#39;final&#39;</span><span class="p">:</span>
<span class="n">version</span> <span class="o">+=</span> <span class="n">kind</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">info</span><span class="o">.</span><span class="n">serial</span><span class="p">)</span>
<span class="k">return</span> <span class="n">version</span>
<span class="n">python_full_version</span> <span class="o">=</span> <span class="n">format_full_version</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">)</span>
<span class="n">implementation_version</span> <span class="o">=</span> <span class="n">format_full_version</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">implementation</span><span class="o">.</span><span class="n">version</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_full_version</span></code> will typically correspond to <code class="docutils literal notranslate"><span class="pre">sys.version.split()[0]</span></code>.</p>
</section>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0496.rst">https://github.com/python/peps/blob/main/peps/pep-0496.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0496.rst">2023-10-11 12:05:51 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#pep-status">PEP Status</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale">Rationale</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#micro-language">Micro-language</a><ul>
<li><a class="reference internal" href="#strings">Strings</a></li>
<li><a class="reference internal" href="#version-numbers">Version numbers</a></li>
</ul>
</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-0496.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>