summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorAarni Koskela <akx@iki.fi>2022-04-06 16:06:08 +0300
committerAarni Koskela <akx@iki.fi>2022-06-14 14:51:56 +0300
commit40fbbf2e7062f8482161576db8366cd4a7caaa93 (patch)
tree3961cece96fb2d29a8c83a017a11d70166dcbad6 /setuptools
parent78cb747d66bda1a6f6649e82690aaf5083a89d69 (diff)
downloadpython-setuptools-git-40fbbf2e7062f8482161576db8366cd4a7caaa93.tar.gz
Allow `file:` for `requires` statements in setup.cfg
Refs #1951
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/config/setupcfg.py30
-rw-r--r--setuptools/tests/config/test_setupcfg.py18
2 files changed, 40 insertions, 8 deletions
diff --git a/setuptools/config/setupcfg.py b/setuptools/config/setupcfg.py
index b2d5c346..caf7694a 100644
--- a/setuptools/config/setupcfg.py
+++ b/setuptools/config/setupcfg.py
@@ -568,15 +568,27 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
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,
@@ -591,11 +603,11 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
"consider using implicit namespaces instead (PEP 420).",
SetuptoolsDeprecationWarning,
),
- '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_list_semicolon,
+ 'tests_require': self._parse_list_semicolon,
'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,
@@ -682,8 +694,10 @@ class ConfigOptionsHandler(ConfigHandler["Distribution"]):
: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):
diff --git a/setuptools/tests/config/test_setupcfg.py b/setuptools/tests/config/test_setupcfg.py
index 904b1ef8..b2563a10 100644
--- a/setuptools/tests/config/test_setupcfg.py
+++ b/setuptools/tests/config/test_setupcfg.py
@@ -884,6 +884,24 @@ class TestOptions:
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
+ [options.extras_require]
+ colors = file:requirements-extra.txt
+ """)
+ )
+
+ tmpdir.join('requirements.txt').write('\ndocutils>=0.3\n\n')
+ tmpdir.join('requirements-extra.txt').write('colorama')
+
+ with get_dist(tmpdir) as dist:
+ assert dist.install_requires == ['docutils>=0.3']
+ assert dist.extras_require == {'colors': ['colorama']}
+
saved_dist_init = _Distribution.__init__