de-RFC Metadata 1.3, with email.policy demo

This commit is contained in:
Daniel Holth 2012-10-20 22:44:40 -04:00
parent 1b8b8f7948
commit c3ca60bb6d
1 changed files with 88 additions and 37 deletions

View File

@ -26,16 +26,17 @@ Version 1.3 of the metadata format adds fields designed to make
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.
Metadata Files
==============
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
appropriate ``email.policy.Policy()``.
In Python 3.2, a serviceable read-only parser is::
@ -46,12 +47,10 @@ There are two standard locations for these metadata files:
* the ``PKG-INFO`` file included in the base directory of Python
source distribution archives (as created by the distutils ``sdist``
command)
* the ``dist-info/METADATA`` files in a Python installation database, as
* the ``.dist-info/METADATA`` files in a Python installation database, as
described in PEP 376.
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.
Encoding
========
@ -141,13 +140,12 @@ Example::
Summary: A module for collecting votes from beagles.
Description (optional)
::::::::::::::::::::::
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 [1]_. For programs that work with the metadata, supporting
@ -155,27 +153,13 @@ markup is optional; programs can also display the contents of the
field as-is. This means that authors should be conservative in
the markup they use.
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
by RFC822 parser [2]_.
Example::
Description: This project provides powerful math functions
|For example, you can use `sum()` to sum numbers:
|
|Example::
|
| >>> sum(1, 2)
| 3
|
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
using a RFC822 reader.
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.
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.
Keywords (optional)
:::::::::::::::::::
@ -278,6 +262,9 @@ Examples::
License: GPL version 3, excluding DRM provisions
The full text of the license would normally be included in a separate
file.
Classifier (multiple use)
:::::::::::::::::::::::::
@ -608,21 +595,24 @@ The fields that benefit from this marker are:
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.
* Changed fields:
- Requires-Dist
- Description
* Added fields:
- Setup-Requires-Dist
- Provides-Extra
- Extension
- Extension
References
==========
@ -637,8 +627,69 @@ Version 1.2 is specified in PEP 345.
.. _`Python Package Index`: http://pypi.python.org/pypi/
.. [2] RFC 822 Long Header Fields:
http://www.freesoft.org/CIE/RFC/822/7.htm
.. [2] PEP 301:
http://www.python.org/dev/peps/pep-0301/
Appendix
========
Parsing and generating the Metadata 1.3 serialization format using
Python 3.3::
# Metadata 1.3 demo
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):
max_line_length = 0
continuation_whitespace = '\t'
def _sanitize_header(self, name, value):
if not isinstance(value, str):
return value
if _has_surrogates(value):
raise NotImplementedError()
else:
return value
def _fold(self, name, value, sanitize):
body = ((self.linesep+self.continuation_whitespace)
.join(value.splitlines()))
return ''.join((name, ': ', body, self.linesep))
if __name__ == "__main__":
import sys
import textwrap
pkg_info = """\
Metadata-Version: 1.3
Name: package
Version: 0.1.0
Summary: A package.
Description: Description
===========
A description of the package.
"""
m = Parser(policy=MetadataPolicy()).parsestr(pkg_info)
m['License'] = 'GPL'
description = m['Description']
description_lines = description.splitlines()
m.set_payload(description_lines[0]
+ '\n'
+ textwrap.dedent('\n'.join(description_lines[1:]))
+ '\n')
del m['Description']
# Correct if sys.stdout.encoding == 'UTF-8':
Generator(sys.stdout, maxheaderlen=0).flatten(m)
Copyright
=========