diff --git a/doc/pyproject_toml.rst b/doc/pyproject_toml.rst index 2fa18ed3..c8daf0ce 100644 --- a/doc/pyproject_toml.rst +++ b/doc/pyproject_toml.rst @@ -67,12 +67,23 @@ requires "configparser; python_version == '2.7'" ] +extras-require + Lists of packages needed for every optional feature. The requirements + are specified in the same format as for ``requires``. The requirements of + the two reserved extras ``test`` and ``doc`` as well as the extra ``dev`` + are installed by ``flit install``. For example: + + .. code-block:: toml + + [tool.flit.metadata.extras-require] + test = ["pytest>=2.7.3", "pytest-cov"] + doc = ["sphinx"] + dev-requires - Packages that are required for development. This field is in the same format - as ``requires``. + Packages that are required for development, other than the ones belonging to + the extras ``test`` and ``doc``. This field is in the same format as ``requires``. - These are not (yet) encoded in the wheel, but are used when doing - ``flit install``. + These are installed by ``flit install`` and encoded in the wheel as extra ``dev``. description-file A path (relative to the .toml file) to a file containing a longer description of your package to show on PyPI. This should be written in `reStructuredText diff --git a/flit/common.py b/flit/common.py index b73ebc96..ad2e7cb1 100644 --- a/flit/common.py +++ b/flit/common.py @@ -227,17 +227,23 @@ class Metadata: requires_external = () provides_extra = () - metadata_version="2.1" + metadata_version = "2.1" - # this is part of metadata spec 2, we are using it for installation but it - # doesn't actually get written to the metadata file + # metadata spec 2 dev_requires = () + extras_require = {} def __init__(self, data): self.name = data.pop('name') self.version = data.pop('version') self.author_email = data.pop('author_email') self.summary = data.pop('summary') + self.extras_require = data.pop('extras_require', {}) + dev_requires = data.pop('dev_requires', None) + if dev_requires is not None: + self.extras_require['dev'] = dev_requires + explicit_extras = data.pop('provides_extra', ()) + self.provides_extra = list(set(explicit_extras) | self.extras_require.keys()) for k, v in data.items(): assert hasattr(self, k), "data does not have attribute '{}'".format(k) setattr(self, k, v) @@ -280,6 +286,10 @@ def write_metadata_file(self, fp): for req in self.requires_dist: fp.write('Requires-Dist: {}\n'.format(req)) + for extra, reqs in self.extras_require.items(): + for req in reqs: + fp.write('Requires-Dist: {}; extra == "{}"\n'.format(req, extra)) + for url in self.project_urls: fp.write('Project-URL: {}\n'.format(url)) diff --git a/flit/inifile.py b/flit/inifile.py index 1920bd2b..0a45b44b 100644 --- a/flit/inifile.py +++ b/flit/inifile.py @@ -34,6 +34,7 @@ class ConfigError(ValueError): 'dist-name', 'entry-points-file', 'description-file', + 'extras-require', } | metadata_list_fields metadata_required_fields = {