257 lines
8.2 KiB
Plaintext
257 lines
8.2 KiB
Plaintext
PEP: 390
|
||
Title: Static metadata for Distutils
|
||
Version: $Revision$
|
||
Last-Modified: $Date$
|
||
Author: Tarek Ziadé <tarek@ziade.org>
|
||
BDFL-Delegate: Nick Coghlan
|
||
Discussions-To: distutils-sig@python.org
|
||
Status: Rejected
|
||
Type: Standards Track
|
||
Topic: Packaging
|
||
Content-Type: text/x-rst
|
||
Created: 10-Oct-2009
|
||
Python-Version: 2.7, 3.2
|
||
Post-History:
|
||
Resolution: https://mail.python.org/pipermail/distutils-sig/2013-April/020597.html
|
||
|
||
Abstract
|
||
========
|
||
|
||
This PEP describes a new section and a new format for the ``setup.cfg`` file,
|
||
that allows describing the Metadata of a package without using ``setup.py``.
|
||
|
||
|
||
Rejection Notice
|
||
================
|
||
|
||
As distutils2 is no longer going to be incorporated into the standard
|
||
library, this PEP was rejected by Nick Coghlan in late April, 2013.
|
||
|
||
A replacement PEP based on :pep:`426` (metadata 2.0) will be created that
|
||
defines the minimum amount of information needed to generate an sdist
|
||
archive given a source tarball or VCS checkout.
|
||
|
||
|
||
Rationale
|
||
=========
|
||
|
||
Today, if you want to list all the Metadata of a distribution (see :pep:`314`)
|
||
that is not installed, you need to use the ``setup.py`` command line interface.
|
||
|
||
So, basically, you download it, and run::
|
||
|
||
$ python setup.py --name
|
||
Distribute
|
||
|
||
$ python setup.py --version
|
||
0.6.4
|
||
|
||
Where ``name`` and ``version`` are metadata fields. This is working fine but
|
||
as soon as the developers add more code in ``setup.py``, this feature might
|
||
break or in worst cases might do unwanted things on the target system.
|
||
|
||
Moreover, when an OS packager wants to get the metadata of a distribution
|
||
he is re-packaging, he might encounter some problems to understand
|
||
the ``setup.py`` file he's working with.
|
||
|
||
So the rationale of this PEP is to provide a way to declare the metadata
|
||
in a static configuration file alongside ``setup.py`` that doesn't require
|
||
any third party code to run.
|
||
|
||
|
||
Adding a ``metadata`` section in ``setup.cfg``
|
||
==============================================
|
||
|
||
The first thing we want to introduce is a ``[metadata]`` section, in the
|
||
``setup.cfg`` file, that may contain any field from the Metadata::
|
||
|
||
[metadata]
|
||
name = Distribute
|
||
version = 0.6.4
|
||
|
||
The ``setup.cfg`` file is used to avoid adding yet another configuration
|
||
file to work with in Distutils.
|
||
|
||
This file is already read by Distutils when a command is executed, and
|
||
if the ``metadata`` section is found, it will be used to fill the metadata
|
||
fields. If an option that corresponds to a Metadata field is given to
|
||
``setup()``, it will override the value that was possibly present in
|
||
``setup.cfg``.
|
||
|
||
Notice that ``setup.py`` is still used and can be required to define some
|
||
options that are not part of the Metadata fields. For instance, the
|
||
``sdist`` command can use options like ``packages`` or ``scripts``.
|
||
|
||
|
||
Multi-lines values
|
||
==================
|
||
|
||
Some Metadata fields can have multiple values. To keep ``setup.cfg`` compatible
|
||
with ``ConfigParser`` and the :rfc:`822` ``LONG HEADER FIELDS`` (see section 3.1.1),
|
||
these are expressed with ``,``-separated values::
|
||
|
||
requires = pywin32, bar > 1.0, foo
|
||
|
||
When this variable is read, the values are parsed and transformed into a list:
|
||
``['pywin32', 'bar > 1.0', 'foo']``.
|
||
|
||
|
||
Context-dependant sections
|
||
==========================
|
||
|
||
The ``metadata`` section will also be able to use context-dependant sections.
|
||
|
||
A context-dependant section is a section with a condition about the execution
|
||
environment. Here's some examples::
|
||
|
||
[metadata]
|
||
name = Distribute
|
||
version = 0.6.4
|
||
|
||
[metadata:sys_platform == 'win32']
|
||
requires = pywin32, bar > 1.0
|
||
obsoletes = pywin31
|
||
|
||
[metadata:os_machine == 'i386']
|
||
requires = foo
|
||
|
||
[metadata:python_version == '2.4' or python_version == '2.5']
|
||
requires = bar
|
||
|
||
[metadata:'linux' in sys_platform]
|
||
requires = baz
|
||
|
||
Every ``[metadata:condition]`` section will be used only if the condition
|
||
is met when the file is read. The background motivation for these
|
||
context-dependant sections is to be able to define requirements that varies
|
||
depending on the platform the distribution might be installed on.
|
||
(see :pep:`314`).
|
||
|
||
The micro-language behind this is the simplest possible: it compares only
|
||
strings, with the ``==`` and ``in`` operators (and their opposites), and
|
||
with the ability to combine expressions. It makes it also easy to understand
|
||
to non-pythoneers.
|
||
|
||
The pseudo-grammar is ::
|
||
|
||
EXPR [in|==|!=|not in] EXPR [or|and] ...
|
||
|
||
where ``EXPR`` belongs to any of those:
|
||
|
||
- python_version = '%s.%s' % (sys.version_info[0], sys.version_info[1])
|
||
- os_name = os.name
|
||
- sys_platform = sys.platform
|
||
- platform_version = platform.version()
|
||
- platform_machine = platform.machine()
|
||
- a free string, like ``2.4``, or ``win32``
|
||
|
||
Notice that ``in`` is restricted to strings, meaning that it is not possible
|
||
to use other sequences like tuples or lists on the right side.
|
||
|
||
Distutils will provide a function that is able to generate the metadata
|
||
of a distribution, given a ``setup.cfg`` file, for the execution environment::
|
||
|
||
>>> from distutils.util import local_metadata
|
||
>>> local_metadata('setup.cfg')
|
||
<DistributionMetadata instance>
|
||
|
||
This means that a vanilla Python will be able to read the metadata of a
|
||
package without running any third party code.
|
||
|
||
Notice that this feature is not restricted to the ``metadata`` namespace.
|
||
Consequently, any other section can be extended with such context-dependant
|
||
sections.
|
||
|
||
Impact on PKG-INFO generation and PEP 314
|
||
=========================================
|
||
|
||
When ``PKG-INFO`` is generated by Distutils, every field that relies on a
|
||
condition will have that condition written at the end of the line, after a `;`
|
||
separator::
|
||
|
||
Metadata-Version: 1.2
|
||
Name: distribute
|
||
Version: 0.6.4
|
||
...
|
||
Requires: pywin32, bar > 1.0; sys_platform == 'win32'
|
||
Requires: foo; os_machine == 'i386'
|
||
Requires: bar; python_version == '2.4' or python_version == '2.5'
|
||
Requires: baz; 'linux' in sys_platform
|
||
Obsoletes = pywin31; sys_platform == 'win32'
|
||
...
|
||
Classifier: Development Status :: 5 - Production/Stable
|
||
Classifier: Intended Audience :: Developers
|
||
Classifier: License :: OSI Approved :: Python Software Foundation License
|
||
|
||
Notice that this file can be opened with the ``DistributionMetadata`` class.
|
||
This class will be able to use the micro-language using the execution
|
||
environment.
|
||
|
||
Let's run in on a ``Python 2.5 i386 Linux``::
|
||
|
||
>>> from distutils.dist import DistributionMetadata
|
||
>>> metadata = DistributionMetadata('PKG_INFO')
|
||
>>> metadata.get_requires()
|
||
['foo', 'bar', 'baz']
|
||
|
||
The execution environment can be overridden in case we want to get the metadata
|
||
for another environment::
|
||
|
||
>>> env = {'python_version': '2.4',
|
||
... 'os_name': 'nt',
|
||
... 'sys_platform': 'win32',
|
||
... 'platform_version': 'MVCC++ 6.0'
|
||
... 'platform_machine': 'i386'}
|
||
...
|
||
>>> metadata = DistributionMetadata('PKG_INFO', environment=env)
|
||
>>> metadata.get_requires()
|
||
['bar > 1.0', 'foo', 'bar']
|
||
|
||
:pep:`314` is changed accordingly, meaning that each field will be able to
|
||
have that extra condition marker.
|
||
|
||
Compatibility
|
||
=============
|
||
|
||
This change is based on a new metadata ``1.2`` format meaning that
|
||
Distutils will be able to distinguish old PKG-INFO files from new ones.
|
||
|
||
The ``setup.cfg`` file change will stay ``ConfigParser``-compatible and
|
||
will not break existing ``setup.cfg`` files.
|
||
|
||
Limitations
|
||
===========
|
||
|
||
We are not providing ``<`` and ``>`` operators at this time, and
|
||
``python_version`` is a regular string. This implies using ``or`` operators
|
||
when a section needs to be restricted to a couple of Python versions.
|
||
Although, if :pep:`386` is accepted, ``python_version`` could be changed
|
||
internally into something comparable with strings, and
|
||
``<`` and ``>`` operators introduced.
|
||
|
||
Last, if a distribution is unable to set all metadata fields in ``setup.cfg``,
|
||
that's fine, the fields will be set to ``UNKNOWN`` when ``local_metadata`` is
|
||
called. Getting ``UNKNOWN`` values will mean that it might be necessary to
|
||
run the ``setup.py`` command line interface to get the whole set of metadata.
|
||
|
||
Acknowledgments
|
||
===============
|
||
|
||
The Distutils-SIG.
|
||
|
||
|
||
Copyright
|
||
=========
|
||
|
||
This document has been placed in the public domain.
|
||
|
||
|
||
..
|
||
Local Variables:
|
||
mode: indented-text
|
||
indent-tabs-mode: nil
|
||
sentence-end-double-space: t
|
||
fill-column: 70
|
||
coding: utf-8
|
||
End:
|