I think this PEP is a significant improvement from its predecessor. It represents features like extras (provides-extra) and build requirements (setup-requires-dist) that are in use in the Python community but cannot be represented in older versions of the format, it finally specifies a UTF-8 encoding, removes RFC 822, provides an extension mechanism, and allows the description to be placed in the document payload.<br>
<br>PEP 426 doesn't have anything to do with the Wheel PEPs 425 and 427, other than that its features are necessary to usefully represent a large number of existing Python packages. How about moving this one along to focus on the other two.<br>
<br>I'm not sure what the Post-History should be. We have been talking about it for a while.<br><br>Thanks,<br><br>Daniel Holth<br><br><br><br>PEP: 426<br>Title: Metadata for Python Software Packages 1.3<br>Version: $Revision$<br>
Last-Modified: $Date$<br>Author: Daniel Holth <<a href="mailto:dholth@fastmail.fm">dholth@fastmail.fm</a>><br>Discussions-To: Distutils SIG<br>Status: Draft<br>Type: Standards Track<br>Content-Type: text/x-rst<br>Created: 30 Aug 2012<br>
<br><br>Abstract<br>========<br><br>This PEP describes a mechanism for adding metadata to Python distributions.<br>It includes specifics of the field names, and their semantics and<br>usage.<br><br>This document specifies version 1.3 of the metadata format.<br>
Version 1.0 is specified in PEP 241.<br>Version 1.1 is specified in PEP 314.<br>Version 1.2 is specified in PEP 345.<br><br>Version 1.3 of the metadata format adds fields designed to make<br>third-party packaging of Python Software easier and defines a<br>
formal extension mechanism.  The fields are "Setup-Requires-Dist"<br>"Provides-Extra", and "Extension".  This version also adds the `extra`<br>variable to the `environment markers` specification and allows the<br>
description to be placed into a payload section.<br><br>Metadata Files<br>==============<br><br>The syntax defined in this PEP is for use with Python distribution<br>metadata files. The file format is a simple UTF-8 encoded Key: value<br>
format with case-insensitive keys and no maximum line length, followed by<br>a blank line and an arbitrary payload.  It is parseable by the ``email``<br>module with an appropriate ``email.policy.Policy()``.<br><br>When ``metadata`` is a Unicode string,<br>
```email.parser.Parser().parsestr(metadata)`` is a serviceable parser.<br><br>There are two standard locations for these metadata files:<br><br>* the ``PKG-INFO`` file included in the base directory of Python<br>  source distribution archives (as created by the distutils ``sdist``<br>
  command)<br>* the ``.dist-info/METADATA`` files in a Python installation database, as<br>  described in PEP 376.<br><br>Other tools involved in Python distribution may also use this format.<br><br>Encoding<br>========<br>
<br>Metadata 1.3 files are UTF-8 with the restriction that keys must be<br>ASCII. Parser implementations should be aware that older versions of<br>the Metadata specification do not specify an encoding.<br><br>Fields<br>======<br>
<br>This section specifies the names and semantics of each of the<br>supported metadata fields.<br><br>In a single Metadata 1.3 file, fields marked with "(optional)" may occur<br>0 or 1 times.  Fields marked with "(multiple use)" may be specified<br>
0, 1 or more times.  Only "Metadata-Version", "Name", "Version", and<br>"Summary" must appear exactly once.  The fields may appear in any order<br>within the file.<br><br>Metadata-Version<br>
::::::::::::::::<br><br>Version of the file format; "1.3" is the only legal value.<br><br>Example::<br><br>    Metadata-Version: 1.3<br><br><br>Name<br>::::<br><br>The name of the distribution.<br><br>Example::<br>
<br>    Name: BeagleVote<br><br><br>Version<br>:::::::<br><br>A string containing the distribution's version number.  This<br>field  must be in the format specified in PEP 386.<br><br>Example::<br><br>    Version: 1.0a2<br>
<br><br>Summary<br>:::::::<br><br>A one-line summary of what the distribution does.<br><br>Example::<br><br>    Summary: A module for collecting votes from beagles.<br><br><br>Platform (multiple use)<br>:::::::::::::::::::::::<br>
<br>A Platform specification describing an operating system supported by<br>the distribution which is not listed in the "Operating System" Trove classifiers.<br>See "Classifier" below.<br><br>Examples::<br>
<br>    Platform: ObscureUnix<br>    Platform: RareDOS<br><br><br>Supported-Platform (multiple use)<br>:::::::::::::::::::::::::::::::::<br><br>Binary distributions containing a metadata file will use the<br>Supported-Platform field in their metadata to specify the OS and<br>
CPU for which the binary distribution was compiled.  The semantics of<br>the Supported-Platform field are not specified in this PEP.<br><br>Example::<br><br>    Supported-Platform: RedHat 7.2<br>    Supported-Platform: i386-win32-2791<br>
<br><br>Description (optional, deprecated)<br>::::::::::::::::::::::::::::::::::<br><br>A longer description of the distribution that can run to several<br>paragraphs.  Software that deals with metadata should not assume<br>
any maximum size for this field.<br><br>The contents of this field can be written using reStructuredText<br>markup [1]_.  For programs that work with the metadata, supporting<br>markup is optional; programs can also display the contents of the<br>
field as-is.  This means that authors should be conservative in<br>the markup they use.<br><br>Since a line separator immediately followed by another line separator<br>indicates the end of the headers section, any line separators in the<br>
description must be suffixed by whitespace to indicate continuation.<br><br>Since Metadata 1.3 the recommended place for the description is in the<br>payload section of the document, after the last header.  The description<br>
does not need to be reformatted when it is included in the payload.<br><br><br>Keywords (optional)<br>:::::::::::::::::::<br><br>A list of additional keywords to be used to assist searching<br>for the distribution in a larger catalog.<br>
<br>Example::<br><br>    Keywords: dog puppy voting election<br><br><br>Home-page (optional)<br>::::::::::::::::::::<br><br>A string containing the URL for the distribution's home page.<br><br>Example::<br><br>    Home-page: <a href="http://www.example.com/~cschultz/bvote/">http://www.example.com/~cschultz/bvote/</a><br>
<br><br>Download-URL (optional)<br>:::::::::::::::::::::::<br><br>A string containing the URL from which this version of the distribution<br>can be downloaded.  (This means that the URL can't be something like<br>".../BeagleVote-latest.tgz", but instead must be ".../BeagleVote-0.45.tgz".)<br>
<br><br>Author (optional)<br>:::::::::::::::::<br><br>A string containing the author's name at a minimum; additional<br>contact information may be provided.<br><br>Example::<br><br>    Author: C. Schultz, Universal Features Syndicate,<br>
            Los Angeles, CA <<a href="mailto:cschultz@peanuts.example.com">cschultz@peanuts.example.com</a>><br><br><br>Author-email (optional)<br>:::::::::::::::::::::::<br><br>A string containing the author's e-mail address.  It contains a name<br>
and e-mail address in the RFC 5322 recommended ``Address Specification``<br>format.<br><br>Example::<br><br>    Author-email: "C. Schultz" <<a href="mailto:cschultz@example.com">cschultz@example.com</a>><br>
<br><br>Maintainer (optional)<br>:::::::::::::::::::::<br><br>A string containing the maintainer's name at a minimum; additional<br>contact information may be provided.<br><br>Note that this field is intended for use when a project is being<br>
maintained by someone other than the original author:  it should be<br>omitted if it is identical to ``Author``.<br><br>Example::<br><br>    Maintainer: C. Schultz, Universal Features Syndicate,<br>            Los Angeles, CA <<a href="mailto:cschultz@peanuts.example.com">cschultz@peanuts.example.com</a>><br>
<br><br>Maintainer-email (optional)<br>:::::::::::::::::::::::::::<br><br>A string containing the maintainer's e-mail address.  It has the same<br>format as ``Author-email``.<br><br>Note that this field is intended for use when a project is being<br>
maintained by someone other than the original author:  it should be<br>omitted if it is identical to ``Author-email``.<br><br>Example::<br><br>    Maintainer-email: "C. Schultz" <<a href="mailto:cschultz@example.com">cschultz@example.com</a>><br>
<br><br>License (optional)<br>::::::::::::::::::<br><br>Text indicating the license covering the distribution where the license<br>is not a selection from the "License" Trove classifiers. See<br>"Classifier" below.  This field may also be used to specify a<br>
particular version of a license which is named via the ``Classifier``<br>field, or to indicate a variation or exception to such a license.<br><br>Examples::<br><br>    License: This software may only be obtained by sending the<br>
            author a postcard, and then the user promises not<br>            to redistribute it.<br><br>    License: GPL version 3, excluding DRM provisions<br><br>The full text of the license would normally be included in a separate<br>
file.<br><br><br>Classifier (multiple use)<br>:::::::::::::::::::::::::<br><br>Each entry is a string giving a single classification value<br>for the distribution.  Classifiers are described in PEP 301 [2].<br><br>Examples::<br>
<br>    Classifier: Development Status :: 4 - Beta<br>    Classifier: Environment :: Console (Text Based)<br><br><br>Requires-Dist (multiple use)<br>::::::::::::::::::::::::::::<br><br>Each entry contains a string naming some other distutils<br>
project required by this distribution.<br><br>The format of a requirement string is identical to that of a<br>distutils project name (e.g., as found in the ``Name:`` field.<br>optionally followed by a version declaration within parentheses.<br>
<br>The distutils project names should correspond to names as found<br>on the `Python Package Index`_.<br><br>Version declarations must follow the rules described in<br>`Version Specifiers`_<br><br>Examples::<br><br>    Requires-Dist: pkginfo<br>
    Requires-Dist: PasteDeploy<br>    Requires-Dist: zope.interface (>3.5.0)<br><br><br>Setup-Requires-Dist (multiple use)<br>::::::::::::::::::::::::::::::::::<br><br>Like Requires-Dist, but names dependencies needed while the<br>
distributions's distutils / packaging `setup.py` / `setup.cfg` is run.<br>Commonly used to generate a manifest from version control.<br><br>Examples::<br><br>    Setup-Requires-Dist: custom_setup_command<br><br>Dependencies mentioned in `Setup-Requires-Dist` may be installed exclusively<br>
for setup and are not guaranteed to be available at run time.<br><br><br>Provides-Dist (multiple use)<br>::::::::::::::::::::::::::::<br><br>Each entry contains a string naming a Distutils project which<br>is contained within this distribution.  This field *must* include<br>
the project identified in the ``Name`` field, followed by the<br>version : Name (Version).<br><br>A distribution may provide additional names, e.g. to indicate that<br>multiple projects have been bundled together.  For instance, source<br>
distributions of the ``ZODB`` project have historically included<br>the ``transaction`` project, which is now available as a separate<br>distribution.  Installing such a source distribution satisfies<br>requirements for both ``ZODB`` and ``transaction``.<br>
<br>A distribution may also provide a "virtual" project name, which does<br>not correspond to any separately-distributed project:  such a name<br>might be used to indicate an abstract capability which could be supplied<br>
by one of multiple projects.  E.g., multiple projects might supply<br>RDBMS bindings for use by a given ORM:  each project might declare<br>that it provides ``ORM-bindings``, allowing other projects to depend<br>only on having at most one of them installed.<br>
<br>A version declaration may be supplied and must follow the rules described<br>in `Version Specifiers`_. The distribution's version number will be implied<br>if none is specified.<br><br>Examples::<br><br>    Provides-Dist: OtherProject<br>
    Provides-Dist: AnotherProject (3.4)<br>    Provides-Dist: virtual_package<br><br><br>Obsoletes-Dist (multiple use)<br>:::::::::::::::::::::::::::::<br><br>Each entry contains a string describing a distutils project's distribution<br>
which this distribution renders obsolete, meaning that the two projects<br>should not be installed at the same time.<br><br>Version declarations can be supplied.  Version numbers must be in the<br>format specified in `Version Specifiers`_.<br>
<br>The most common use of this field will be in case a project name<br>changes, e.g. Gorgon 2.3 gets subsumed into Torqued Python 1.0.<br>When you install Torqued Python, the Gorgon distribution should be<br>removed.<br>
<br>Examples::<br><br>    Obsoletes-Dist: Gorgon<br>    Obsoletes-Dist: OtherProject (<3.0)<br><br><br>Requires-Python (optional)<br>::::::::::::::::::::::::::<br><br>This field specifies the Python version(s) that the distribution is<br>
guaranteed to be compatible with.<br><br>Version numbers must be in the format specified in `Version Specifiers`_.<br><br>Examples::<br><br>    Requires-Python: 2.5<br>    Requires-Python: >2.1<br>    Requires-Python: >=2.3.4<br>
    Requires-Python: >=2.5,<2.7<br><br><br>Requires-External (multiple use)<br>::::::::::::::::::::::::::::::::<br><br>Each entry contains a string describing some dependency in the<br>system that the distribution is to be used.  This field is intended to<br>
serve as a hint to downstream project maintainers, and has no<br>semantics which are meaningful to the ``distutils`` distribution.<br><br>The format of a requirement string is a name of an external<br>dependency, optionally followed by a version declaration within<br>
parentheses.<br><br>Because they refer to non-Python software releases, version numbers<br>for this field are **not** required to conform to the format<br>specified in PEP 386:  they should correspond to the<br>version scheme used by the external dependency.<br>
<br>Notice that there's is no particular rule on the strings to be used.<br><br>Examples::<br><br>    Requires-External: C<br>    Requires-External: libpng (>=1.5)<br><br><br>Project-URL (multiple use)<br>::::::::::::::::::::::::::<br>
<br>A string containing a label and a browsable URL for the project, separated<br>by the last occurrence of comma and space ", ".<br><br>Example::<br><br>    Bug, Issue Tracker, <a href="http://bitbucket.org/tarek/distribute/issues/">http://bitbucket.org/tarek/distribute/issues/</a><br>
<br>The label is a free text.<br><br><br>Provides-Extra (multiple use)<br>:::::::::::::::::::::::::::::<br><br>A string containing the name of an optional feature. Must be printable<br>ASCII, not containing whitespace, comma (,), or square brackets [].<br>
May be used to make a dependency conditional on whether the optional<br>feature has been requested.<br><br>Example::<br><br>    Name: beaglevote<br>    Provides-Extra: pdf<br>    Requires-Dist: reportlab; extra == 'pdf'<br>
    Requires-Dist: nose; extra == 'test'<br>    Requires-Dist: sphinx; extra == 'doc'<br><br>A second distribution requires an optional dependency by placing it<br>inside square brackets and can request multiple features by separating<br>
them with a comma (,).<br><br>The full set of requirements is the union of the `Requires-Dist` sets<br>evaluated with `extra` set to `None` and then to the name of each<br>requested feature.<br><br>Example::<br><br>    Requires-Dist: beaglevote[pdf]<br>
        -> requires beaglevote, reportlab<br><br>    Requires-Dist: beaglevote[test, doc]<br>        -> requires beaglevote, sphinx, nose<br><br>Two feature names `test` and `doc` are reserved to mark dependencies that<br>
are needed for running automated tests and generating documentation,<br>respectively.<br><br>It is legal to specify `Provides-Extra` without referencing it in any<br>`Requires-Dist`. It is an error to request a feature name that has<br>
not been declared with `Provides-Extra`.<br><br><br>Extension (multiple use)<br>::::::::::::::::::::::::<br><br>An ASCII string, not containing whitespace or the / character, that<br>indicates the presence of extended metadata. Additional tags defined by<br>
an `Extension: Chili` must be of the form `Chili/Name`::<br><br>    Extension: Chili<br>    Chili/Type: Poblano<br>    Chili/Heat: Mild<br><br>An implementation might iterate over all the declared `Extension:`<br>fields to invoke the processors for those extensions.  As the order of<br>
the fields is not used, the `Extension: Chili` field may appear before<br>or after its declared tags `Chili/Type:` etc.<br><br><br>Version Specifiers<br>==================<br><br>Version specifiers are a series of conditional operators and<br>
version numbers, separated by commas.  Conditional operators<br>must be one of "<", ">", "<=", ">=", "==" and "!=".<br><br>Any number of conditional operators can be specified, e.g.<br>
the string ">1.0, !=1.3.4, <2.0" is a legal version declaration.<br>The comma (",") is equivalent to the **and** operator.<br><br>Each version number must be in the format specified in PEP 386.<br>
<br>When a version is provided, it always includes all versions that<br>starts with the same value. For example the "2.5" version of Python<br>will include versions like "2.5.2" or "2.5.3". Pre and post releases<br>
in that case are excluded. So in our example, versions like "2.5a1" are<br>not included when "2.5" is used. If the first version of the range is<br>required, it has to be explicitly given. In our example, it will be<br>
"2.5.0".<br><br>Notice that some projects might omit the ".0" prefix for the first release<br>of the "2.5.x" series:<br><br>- 2.5<br>- 2.5.1<br>- 2.5.2<br>- etc.<br><br>In that case, "2.5.0" will have to be explicitly used to avoid any confusion<br>
between the "2.5" notation that represents the full range. It is a recommended<br>practice to use schemes of the same length for a series to completely avoid<br>this problem.<br><br>Some Examples:<br><br>- ``Requires-Dist: zope.interface (3.1)``: any version that starts with 3.1,<br>
  excluding post or pre-releases.<br>- ``Requires-Dist: zope.interface (==3.1)``: equivalent to ``Requires-Dist:<br>  zope.interface (3.1)``.<br>- ``Requires-Dist: zope.interface (3.1.0)``: any version that starts with<br>
  3.1.0, excluding post or pre-releases. Since that particular project doesn't<br>  use more than 3 digits, it also means "only the 3.1.0 release".<br>- ``Requires-Python: 3``: Any Python 3 version, no matter wich one, excluding<br>
  post or pre-releases.<br>- ``Requires-Python: >=2.6,<3``: Any version of Python 2.6 or 2.7, including<br>  post releases of 2.6, pre and post releases of 2.7. It excludes pre releases<br>  of Python 3.<br>- ``Requires-Python: 2.6.2``: Equivalent to ">=2.6.2,<2.6.3". So this includes<br>
  only Python 2.6.2. Of course, if Python was numbered with 4 digits, it would<br>  have include all versions of the 2.6.2 series.<br>- ``Requires-Python: 2.5.0``: Equivalent to ">=2.5.0,<2.5.1".<br>- ``Requires-Dist: zope.interface (3.1,!=3.1.3)``: any version that starts with<br>
  3.1, excluding post or pre-releases of 3.1 *and* excluding any version that<br>  starts with "3.1.3". For this particular project, this means: "any version<br>  of the 3.1 series but not 3.1.3". This is equivalent to:<br>
  ">=3.1,!=3.1.3,<3.2".<br><br>Environment markers<br>===================<br><br>An **environment marker** is a marker that can be added at the end of a<br>field after a semi-colon (";"), to add a condition about the execution<br>
environment.<br><br>Here are some example of fields using such markers::<br><br>   Requires-Dist: pywin32 (>1.0); sys.platform == 'win32'<br>   Obsoletes-Dist: pywin31; sys.platform == 'win32'<br>   Requires-Dist: foo (1,!=1.3); platform.machine == 'i386'<br>
   Requires-Dist: bar; python_version == '2.4' or python_version == '2.5'<br>   Requires-External: libxslt; 'linux' in sys.platform<br><br>The micro-language behind this is a simple subset of Python: it compares<br>
only strings, with the ``==`` and ``in`` operators (and their opposites),<br>and with the ability to combine expressions. Parenthesis are supported<br>for grouping.<br><br>The pseudo-grammar is ::<br><br>    EXPR [in|==|!=|not in] EXPR [or|and] ...<br>
<br>where ``EXPR`` belongs to any of those:<br><br>- python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1])<br>- python_full_version = sys.version.split()[0]<br>- <a href="http://os.name">os.name</a> = <a href="http://os.name">os.name</a><br>
- sys.platform = sys.platform<br>- platform.version = platform.version()<br>- platform.machine = platform.machine()<br>- platform.python_implementation = platform.python_implementation()<br>- a free string, like ``'2.4'``, or ``'win32'``<br>
- extra = (name of requested feature) or None<br><br>Notice that ``in`` is restricted to strings, meaning that it is not possible<br>to use other sequences like tuples or lists on the right side.<br><br>The fields that benefit from this marker are:<br>
<br>- Requires-Python<br>- Requires-External<br>- Requires-Dist<br>- Setup-Requires-Dist<br>- Provides-Dist<br>- Obsoletes-Dist<br>- Classifier<br><br>(The `extra` variable is only meaningful for Requires-Dist.)<br><br>Summary of Differences From PEP 345<br>
===================================<br><br>* Metadata-Version is now 1.3.<br><br>* Values are now expected to be UTF-8.<br><br>* A payload (containing the description) may appear after the headers.<br><br>* Added `extra` to environment markers.<br>
<br>* Most fields are now optional.<br><br>* Changed fields:<br><br>  - Description<br>  - Project-URL<br>  - Requires-Dist<br><br>* Added fields:<br><br>  - Extension<br>  - Provides-Extra<br>  - Setup-Requires-Dist<br>  <br>
References<br>==========<br><br>This document specifies version 1.3 of the metadata format.<br>Version 1.0 is specified in PEP 241.<br>Version 1.1 is specified in PEP 314.<br>Version 1.2 is specified in PEP 345.<br><br>.. [1] reStructuredText markup:<br>
   <a href="http://docutils.sourceforge.net/">http://docutils.sourceforge.net/</a><br><br>.. _`Python Package Index`: <a href="http://pypi.python.org/pypi/">http://pypi.python.org/pypi/</a><br><br>.. [2] PEP 301:<br>   <a href="http://www.python.org/dev/peps/pep-0301/">http://www.python.org/dev/peps/pep-0301/</a><br>
<br>Appendix<br>========<br><br>Parsing and generating the Metadata 1.3 serialization format using<br>Python 3.3::<br><br>    # Metadata 1.3 demo<br>    from email.generator import Generator<br>    from email import header <br>
    from email.parser import Parser <br>    from email.policy import Compat32 <br>    from email.utils import _has_surrogates<br><br>    class MetadataPolicy(Compat32):<br>        max_line_length = 0<br>        continuation_whitespace = '\t'<br>
        <br>        def _sanitize_header(self, name, value):<br>            if not isinstance(value, str):<br>                return value<br>            if _has_surrogates(value):<br>                raise NotImplementedError()<br>
            else:<br>                return value<br><br>        def _fold(self, name, value, sanitize):<br>            body = ((self.linesep+self.continuation_whitespace)<br>                    .join(value.splitlines()))<br>
            return ''.join((name, ': ', body, self.linesep))<br><br>    if __name__ == "__main__":<br>        import sys<br>        import textwrap<br><br>        pkg_info = """\<br>
    Metadata-Version: 1.3<br>    Name: package<br>    Version: 0.1.0<br>    Summary: A package.<br>    Description: Description<br>        ===========<br>        <br>        <br>        A description of the package.<br><br>
    """<br><br>        m = Parser(policy=MetadataPolicy()).parsestr(pkg_info)<br><br>        m['License'] = 'GPL'<br>        description = m['Description']<br>        description_lines = description.splitlines()<br>
        m.set_payload(description_lines[0] <br>                + '\n' <br>                + textwrap.dedent('\n'.join(description_lines[1:])) <br>                + '\n')<br>        del m['Description']<br>
<br>        # Correct if sys.stdout.encoding == 'UTF-8':<br>        Generator(sys.stdout, maxheaderlen=0).flatten(m)<br><br>Copyright<br>=========<br><br>This document has been placed in the public domain.<br><br>
<br><br>..<br>   Local Variables:<br>   mode: indented-text<br>   indent-tabs-mode: nil<br>   sentence-end-double-space: t<br>   fill-column: 70<br>   End:<br><br>