third-party packaging of Python Software easier and defines a
formal extension mechanism. The fields are "Setup-Requires-Dist"
"Provides-Extra", and "Extension". This version also adds the `extra`
-variable to the `environment markers` specification.
+variable to the `environment markers` specification and allows the
+description to be placed into a payload section.
The syntax defined in this PEP is for use with Python distribution
metadata files. The file format is a simple UTF-8 encoded Key: value
-format with no maximum line length. It is parseable by the ``email``
-module with an appropriate ``email.policy.Policy()``. The field names
-listed in the `Fields`_ section are used as the header names.
+format with no maximum line length, followed by a blank line and an
+arbitrary payload. It is parseable by the ``email`` module with an
In Python 3.2, a serviceable read-only parser is::
* the ``PKG-INFO`` file included in the base directory of Python
source distribution archives (as created by the distutils ``sdist``
-* the ``dist-info/METADATA`` files in a Python installation database, as
+* the ``dist-info/METADATA`` files in a Python installation database, as
-Other tools involved in Python distribution may choose to record this
-metadata in additional tool-specific locations (e.g. as part of a
-binary distribution archive format).
+Other tools involved in Python distribution may also use this format.
Summary: A module for collecting votes from beagles.
+Description (optional, deprecated)
A longer description of the distribution that can run to several
paragraphs. Software that deals with metadata should not assume
-any maximum size for this field, though people shouldn't include
-their instruction manual as the description.
+any maximum size for this field.
The contents of this field can be written using reStructuredText
markup _. For programs that work with the metadata, supporting
field as-is. This means that authors should be conservative in
-To support empty lines and lines with indentation and maintain
-compatibility with ``email.parser.Parser()``, any CRLF character has to
-be suffixed by 7 spaces followed by a pipe ("|") char. As a result, the
-Description field is encoded into a folded field that can be interpreted
+Since a line separator immediately followed by another line separator
+indicates the end of the headers section, any line separator must be
+suffixed by whitespace to indicate continuation.
- Description: This project provides powerful math functions
- |For example, you can use `sum()` to sum numbers:
-This encoding implies that any occurences of a CRLF followed by 7 spaces
-and a pipe char have to be replaced by a single CRLF when the field is unfolded
+Since Metadata 1.3 the recommended place for the description is in the
+payload section of the document, after the last header. The description
+needs no special formatting when included in the payload.
License: GPL version 3, excluding DRM provisions
+The full text of the license would normally be included in a separate
Classifier (multiple use)
Summary of Differences From PEP 345
Values are now expected to be UTF-8
-* Metadata-Version is now 1.3.
+* Values are now expected to be UTF-8.
+* A payload (containing the description) may appear after the headers.
* Added `extra` to environment markers.
.. _`Python Package Index`: http://pypi.python.org/pypi/
-..  RFC 822 Long Header Fields:
+Parsing and generating the Metadata 1.3 serialization format using
+ from email.generator import Generator
+ from email import header
+ from email.parser import Parser
+ from email.policy import Compat32
+ from email.utils import _has_surrogates
+ class MetadataPolicy(Compat32):
+ continuation_whitespace = '\t'
+ def _sanitize_header(self, name, value):
+ if not isinstance(value, str):
+ if _has_surrogates(value):
+ raise NotImplementedError()
+ def _fold(self, name, value, sanitize):
+ body = ((self.linesep+self.continuation_whitespace)
+ return ''.join((name, ': ', body, self.linesep))
+ if __name__ == "__main__":
+ Description: Description
+ A description of the package.
+ m = Parser(policy=MetadataPolicy()).parsestr(pkg_info)
+ description = m['Description']
+ description_lines = description.splitlines()
+ + textwrap.dedent('\n'.join(description_lines[1:]))
+ # Correct if sys.stdout.encoding == 'UTF-8':
+ Generator(sys.stdout, maxheaderlen=0).flatten(m)