de-RFC Metadata 1.3, with email.policy demo
This commit is contained in:
parent
1b8b8f7948
commit
c3ca60bb6d
125
pep-0426.txt
125
pep-0426.txt
|
@ -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
|
||||
=========
|
||||
|
|
Loading…
Reference in New Issue