[Distutils] New PEP : dependency specification

Robert Collins robertc at robertcollins.net
Sun Nov 8 16:43:06 EST 2015


Here is the full diff vs the last push to github.

diff --git a/dependency-specification.rst b/dependency-specification.rst
index 6f85b98..03f2a0d 100644
--- a/dependency-specification.rst
+++ b/dependency-specification.rst
@@ -52,10 +52,7 @@ Examples

 All features of the language shown with a name based lookup::

-    requests \
-        [security] >= 2.8.1, == 2.8.* \
-        ; python_version < "2.7.10" \
-        # Fix HTTPS on older Python versions.
+    requests [security,tests] >= 2.8.1, == 2.8.* ; python_version < "2.7.10"

 A minimal URL based lookup::

@@ -77,29 +74,25 @@ We first cover the grammar briefly and then drill
into the semantics of each
 section later.

 A distribution specification is written in ASCII text. We use ABNF [#abnf]_ to
-provide a precise grammar. Specifications may have comments starting with a
-'#' and running to the end of the line::
-
-    comment       = "#" *(WSP / VCHAR)
-
-Specifications may be spread across multiple lines if desired using
-continuations - a single backslash followed by a new line ('\\\\n')::
-
-    CSP           = 1*(WSP / ("\\" LF))
+provide a precise grammar. The grammar covers just the specification itself.
+The expectation is that the specification will be embedded into a larger
+system which offers framing such as comments, multiple line support via
+continuations, or other such features.

 Versions may be specified according to the PEP-440 [#pep440]_ rules. (Note:
 URI is defined in std-66 [#std66]_::

     version-cmp   = "<" / "<=" / "!=" / "==" / ">=" / ">" / "~=" / "==="
     version       = 1*( DIGIT / ALPHA / "-" / "_" / "." / "*" )
-    versionspec   = ["("] version-cmp version *(',' version-cmp version) [")"]
+    version-inner = version-cmp version *(',' version-cmp version)
+    versionspec   = ("(" version-inner ")") / version-inner
     urlspec       = "@" URI

 Environment markers allow making a specification only take effect in some
 environments::

     marker-op     = version-cmp / "in" / "not in"
-    python-str-c  = (WSP / ALPHA / DIGIT / "(" / ")" / "." / "{" / "}" /
+    python-str-c  = WSP / ALPHA / DIGIT / "(" / ")" / "." / "{" / "}" /
                     "-" / "_" / "*"
     python-str    = "'" *(python-str-c / DQUOTE) "'"
     python-str    =/ DQUOTE *(python-str-c / "'") DQUOTE
@@ -109,10 +102,12 @@ environments::
                     "platform_python_implementation" / "implementation_name" /
                     "implementation_version" / "platform_dist_name"
                     "platform_dist_version" / "platform_dist_id"
-    marker-expr   = "(" marker ")" / (marker-var [marker-op marker-var])
-    marker        = marker-expr *( ("and" / "or") marker-expr)
-    name-marker   = ";" *CSP marker
-    url-marker    = ";" 1*CSP marker
+    marker-var    =/ "extra" ; ONLY when defined by a containing layer
+    marker-expr   = "(" *WSP marker *WSP ")"
+                  =/ (marker-var [*WSP marker-op *WSP marker-var])
+    marker        = *WSP marker-expr *( *WSP ("and" / "or") *WSP marker-expr)
+    name-marker   = ";" *WSP marker
+    url-marker    = ";" 1*WSP marker

 Optional components of a distribution may be specified using the extras
 field::
@@ -123,31 +118,21 @@ field::

 Giving us a rule for name based requirements::

-    name_req      = name [CSP extras] [CSP versionspec] [CSP name-marker]
+    name_req      = name [*WSP extras] [*WSP versionspec] [*WSP name-marker]

 And a rule for direct reference specifications::

-    url_req       = name [CSP extras] urlspec [CSP url-marker]
+    url_req       = name [*WSP extras] urlspec [*WSP url-marker]

 Leading to the unified rule that can specify a dependency::

-    specification = (name_req / location_req) [CSP comment]
+    specification = name_req / location_req

 Whitespace
 ----------

 Non line-breaking whitespace is optional and has no semantic meaning.

-A line break indicates the end of a specification. Specifications can be
-continued across multiple lines using a continuation.
-
-Comments
---------
-
-A specification can have a comment added to it by starting the comment with a
-"#". After a "#" the rest of the line can contain any text whatsoever.
-Continuations within a comment are ignored.
-
 Names
 -----

@@ -209,42 +194,45 @@ either side is not a valid version, then the
comparsion falls back to the same
 behaviour as in for string in Python if the operator exists in Python. For
 those operators which are not defined in Python, the result should be False.

-The variables in the marker grammar such as "os_name" resolve to values looked
-up in the Python runtime. If a particular value is not available (such as
-``sys.implementation.name`` in versions of Python prior to 3.3, or
-``platform.dist()`` on non-Linux systems), the default value will be used.
+User supplied constants are always encoded as strings with either ``'`` or
+``"`` quote marks. Note that backslash escapes are not defined, but existing
+implementations do support them them. They are not included in this
+specification because none of the variables to which constants can be compared
+contain quote-requiring values.

+The variables in the marker grammar such as "os_name" resolve to values looked
+up in the Python runtime. With the exception of "extra" all values are defined
+on all Python versions today - it is an error in the implementation of markers
+if a value is not defined.
+
+Unknown variables must raise a SyntaxError rather than resulting in a
+comparison that evaluates to True or False.
+
+The "extra" variable is special. It is used by wheels to signal which
+specifications apply to a given extra in the wheel ``METADATA`` file, but
+since the ``METADATA`` file is based on a draft version of PEP-426, there is
+no current specification for this. Regardless, outside of a context where this
+special handling is taking place, the "extra" variable should result in a
+SyntaxError like all other unknown variables.
+
 .. list-table::
    :header-rows: 1

    * - Marker
      - Python equivalent
      - Sample values
-     - Default if unavailable
    * - ``os_name``
      - ``os.name``
      - ``posix``, ``java``
-     - ""
    * - ``sys_platform``
      - ``sys.platform``
      - ``linux``, ``darwin``, ``java1.8.0_51``
-     - ""
-   * - ``platform_release``
-     - ``platform.release()``
-     - ``3.14.1-x86_64-linode39``, ``14.5.0``, ``1.8.0_51``
-     - ""
    * - ``platform_machine``
      - ``platform.machine()``
      - ``x86_64``
-     - ""
-   * - ``platform_python_implementation``
+   * - ``python_implementation``
      - ``platform.python_implementation()``
      - ``CPython``, ``Jython``
-     - ""
-   * - ``implementation_name``
-     - ``sys.implementation.name``
-     - ``cpython``
-     - ""
    * - ``platform_version``
      - ``platform.version()``
      - ``#1 SMP Fri Apr 25 13:07:35 EDT 2014``
@@ -252,51 +240,16 @@ up in the Python runtime. If a particular value
is not available (such as
        ``Java HotSpot(TM) 64-Bit Server VM, 25.51-b03, Oracle Corporation``

        ``Darwin Kernel Version 14.5.0: Wed Jul 29 02:18:53 PDT 2015;
root:xnu-2782.40.9~2/RELEASE_X86_64``
-     - ""
-   * - ``platform_dist_name``
-     - ``platform.dist()[0]``
-     - ``Ubuntu``
-     - ""
-   * - ``platform_dist_version``
-     - ``platform.dist()[1]``
-     - ``14.04``
-     - ""
-   * - ``platform_dist_id``
-     - ``platform.dist()[2]``
-     - ``trusty``
-     - ""
    * - ``python_version``
      - ``platform.python_version()[:3]``
      - ``3.4``, ``2.7``
-     - "0"
    * - ``python_full_version``
      - see definition below
      - ``3.4.0``, ``3.5.0b1``
-     - "0"
-   * - ``implementation_version``
-     - see definition below
-     - ``3.4.0``, ``3.5.0b1``
-     - "0"
-
-The ``python_full_version`` and ``implementation_version`` marker variables
-are derived from ``sys.version_info`` and ``sys.implementation.version``
-respectively, in accordance with the following algorithm::
-
-    def format_full_version(info):
-        version = '{0.major}.{0.minor}.{0.micro}'.format(info)
-        kind = info.releaselevel
-        if kind != 'final':
-            version += kind[0] + str(info.serial)
-        return version
-
-    python_full_version = format_full_version(sys.version_info)
-    implementation_version = format_full_version(sys.implementation.version)
-
-``python_full_version`` will typically correspond to
``sys.version.split()[0]``.
-
-If a particular version number value is not available (such as
-``sys.implementation.version`` in versions of Python prior to 3.3) the
-corresponding marker variable returned by setuptools will be set to ``0``
+   * - ``extra``
+     - A SyntaxError except when defined by the context interpreting the
+       specification.
+     - ``test``

 Backwards Compatibility
 =======================


More information about the Distutils-SIG mailing list