After this PEP was initially drafted,PEP 508 was developed and submitted tofully specify the dependency declaration syntax, including environment markers.As a result, this PEP ended up being rejected in favour of the more comprehensivePEP 508.
Anenvironment marker describes a condition about the current executionenvironment. They are used to indicate when certain dependencies are onlyrequired in particular environments, and to indicate supported platformsfor distributions with additional constraints beyond the availability of aPython runtime.
Environment markers were first specified inPEP 345.PEP 426(which would replacePEP 345) proposed extensions to the markers.When 2.7.10 was released, even these extensions became insufficient due totheir reliance on simple lexical comparisons, and thus this PEP has been born.
Many Python packages are written with portability in mind.
For many packages this means they aim to support a wide range ofPython releases. If they depend on libraries such asargparse -which started as external libraries, but later got incorporated intocore - specifying a single set of requirements is difficult, as theset of required packages differs depending on the version of Python inuse.
For other packages, designing for portability means supportingmultiple operating systems. However, the significant differencesbetween them may mean that particular dependencies are only needed onparticular platforms (relying onpywin32 only on Windows, forexample)”
Environment Markers attempt to provide more flexibility in a list ofrequirements by allowing the developer to list requirements that arespecific to a particular environment.
Here are some examples of such markers inside a requirements.txt:
pywin32>=1.0;sys_platform=='win32'unittest2>=2.0,<3.0;python_version=='2.4'orpython_version=='2.5'backports.ssl_match_hostname>=3.4;python_version<'2.7.9'or(python_version>='3.0'andpython_version<'3.4')
And here’s an example of some conditional metadata included insetup.py for a distribution that requires PyWin32 both at runtime andbuildtime when using Windows:
setup(install_requires=["pywin32 > 1.0 : sys.platform == 'win32'"],setup_requires=["pywin32 > 1.0 : sys.platform == 'win32'"])
The micro-language behind this is as follows. It compares:
== andin operators (and their opposites)<,<=,>=, and< operatorsin addition to those supported for stringsThe usual boolean operatorsand andor can be used to combineexpressions, and parentheses are supported for grouping.
The pseudo-grammar is
MARKER:EXPR[(and|or)EXPR]*EXPR:("("MARKER")")|(STREXPR|VEREXPR)STREXPR:STRING[STRCMPOPSTREXPR]STRCMPOP:==|!=|in|notinVEREXPR:VERSION[VERCMPOPVEREXPR]VERCMPOP:(==|!=|<|>|<=|>=)
SUBEXPR is either a Python string (such as'win32') or one oftheStrings marker variables listed below.
VEREXPR is aPEP 440 version identifier, or one of theVersionnumber marker variables listed below. Comparisons betweenversion numbers are done usingPEP 440 semantics.
os_name:os.namesys_platform:sys.platformplatform_release:platform.release()implementation_name:sys.implementation.nameplatform_machine:platform.machine()platform_python_implementation:platform.python_implementation()If a particular string value is not available (such assys.implementation.namein versions of Python prior to 3.3), the corresponding markervariable MUST be considered equivalent to the empty string.
If a particular version number value is not available (such assys.implementation.version in versions of Python prior to 3.3) thecorresponding marker variable MUST be considered equivalent to0
python_version:platform.python_version()[:3]python_full_version: see definition belowplatform_version:platform.version()implementation_version: see definition belowThepython_full_version andimplementation_version marker variablesare derived fromsys.version_info andsys.implementation.versionrespectively, in accordance with the following algorithm:
defformat_full_version(info):version='{0.major}.{0.minor}.{0.micro}'.format(info)kind=info.releaselevelifkind!='final':version+=kind[0]+str(info.serial)returnversionpython_full_version=format_full_version(sys.version_info)implementation_version=format_full_version(sys.implementation.version)
python_full_version will typically correspond tosys.version.split()[0].
This document has been placed in the public domain.
Source:https://github.com/python/peps/blob/main/peps/pep-0496.rst
Last modified:2025-02-01 08:59:27 GMT