Skip to content

Commit

Permalink
Allow file: for requires statements in setup.cfg
Browse files Browse the repository at this point in the history
Refs #1951
  • Loading branch information
akx committed Apr 6, 2022
1 parent b686a31 commit 2dbbabb
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 16 deletions.
21 changes: 13 additions & 8 deletions docs/userguide/declarative_config.rst
Expand Up @@ -192,28 +192,28 @@ obsoletes list-comma
Options
-------

======================= =================================== =============== =========
======================= =================================== =============== ====================
Key Type Minimum Version Notes
======================= =================================== =============== =========
======================= =================================== =============== ====================
zip_safe bool
setup_requires list-semi 36.7.0
install_requires list-semi
extras_require section [#opt-2]_
setup_requires file:, list-semi 36.7.0 [#opt-5]_
install_requires file:, list-semi [#opt-5]_
extras_require file:, section [#opt-2]_, [#opt-5]_
python_requires str 34.4.0
entry_points file:, section 51.0.0
scripts list-comma
eager_resources list-comma
dependency_links list-comma
tests_require list-semi
tests_require file:, list-semi [#opt-5]_
include_package_data bool
packages find:, find_namespace:, list-comma [#opt-3]_
package_dir dict
package_data section [#opt-1]_
exclude_package_data section
namespace_packages list-comma
py_modules list-comma 34.4.0
py_modules list-comma 34.4.0
data_files section 40.6.0 [#opt-4]_
======================= =================================== =============== =========
======================= =================================== =============== ====================

**Notes**:

Expand Down Expand Up @@ -243,6 +243,11 @@ data_files section 40.6.0 [#
.. [#opt-4] ``data_files`` is deprecated and should be avoided.
Please check :doc:`/userguide/datafiles` for more information.
.. [#opt-5] ``file:`` directives for reading requirements are supported since version 63.0.
The format for the file is basically the same as for a ``requirements.txt`` file.
Library developers should avoid tightly pinning their dependencies to a specific
version (e.g. via a "locked" requirements file).
Compatibility with other tools
==============================
Expand Down
30 changes: 22 additions & 8 deletions setuptools/config/setupcfg.py
Expand Up @@ -567,15 +567,27 @@ def __init__(
self.root_dir = target_obj.src_root
self.package_dir: Dict[str, str] = {} # To be filled by `find_packages`

@classmethod
def _parse_list_semicolon(cls, value):
return cls._parse_list(value, separator=';')

def _parse_file_in_root(self, value):
return self._parse_file(value, root_dir=self.root_dir)

def _parse_requirements_list(self, value):
# Parse a requirements list, either by reading in a `file:`, or a list.
parsed = self._parse_list_semicolon(self._parse_file_in_root(value))
# Filter it to only include lines that are not comments. `parse_list`
# will have stripped each line and filtered out empties.
return [line for line in parsed if not line.startswith("#")]

@property
def parsers(self):
"""Metadata item name to parser function mapping."""
parse_list = self._parse_list
parse_list_semicolon = partial(self._parse_list, separator=';')
parse_bool = self._parse_bool
parse_dict = self._parse_dict
parse_cmdclass = self._parse_cmdclass
parse_file = partial(self._parse_file, root_dir=self.root_dir)

return {
'zip_safe': parse_bool,
Expand All @@ -585,11 +597,11 @@ def parsers(self):
'eager_resources': parse_list,
'dependency_links': parse_list,
'namespace_packages': parse_list,
'install_requires': parse_list_semicolon,
'setup_requires': parse_list_semicolon,
'tests_require': parse_list_semicolon,
'install_requires': self._parse_requirements_list,
'setup_requires': self._parse_requirements_list,
'tests_require': self._parse_requirements_list,
'packages': self._parse_packages,
'entry_points': parse_file,
'entry_points': self._parse_file_in_root,
'py_modules': parse_list,
'python_requires': SpecifierSet,
'cmdclass': parse_cmdclass,
Expand Down Expand Up @@ -676,8 +688,10 @@ def parse_section_extras_require(self, section_options):
:param dict section_options:
"""
parse_list = partial(self._parse_list, separator=';')
parsed = self._parse_section_to_dict(section_options, parse_list)
parsed = self._parse_section_to_dict(
section_options,
self._parse_requirements_list,
)
self['extras_require'] = parsed

def parse_section_data_files(self, section_options):
Expand Down
21 changes: 21 additions & 0 deletions setuptools/tests/config/test_setupcfg.py
Expand Up @@ -881,6 +881,27 @@ def test_cmdclass(self, tmpdir):
assert cmdclass.__module__ == "custom_build"
assert module_path.samefile(inspect.getfile(cmdclass))

def test_requirements_file(self, tmpdir):
fake_env(
tmpdir,
DALS("""
[options]
install_requires = file:requirements.txt
tests_require = file:requirements-test.txt
[options.extras_require]
colors = file:requirements-extra.txt
""")
)

tmpdir.join('requirements.txt').write('\ndocutils>=0.3\n\n')
tmpdir.join('requirements-test.txt').write(' # comment\npytest\n# comment\n')
tmpdir.join('requirements-extra.txt').write('colorama')

with get_dist(tmpdir) as dist:
assert dist.install_requires == ['docutils>=0.3']
assert dist.tests_require == ['pytest']
assert dist.extras_require == {'colors': ['colorama']}


saved_dist_init = _Distribution.__init__

Expand Down

0 comments on commit 2dbbabb

Please sign in to comment.