Commit 318f739d authored by Paul Ganssle's avatar Paul Ganssle

Add requirement parsing in setuptools.build_meta

This fixes GH #1682 by porting the pkg_resources requirement parsing
logic into setuptools.build_meta, so that all valid requirement
specifiers passed to setup_requires will be added to the
get_requires_for_build_* function outputs.

Fixes GH #1682
parent 1aa781cd
...@@ -36,6 +36,8 @@ import contextlib ...@@ -36,6 +36,8 @@ import contextlib
import setuptools import setuptools
import distutils import distutils
from setuptools._vendor import six
__all__ = ['get_requires_for_build_sdist', __all__ = ['get_requires_for_build_sdist',
'get_requires_for_build_wheel', 'get_requires_for_build_wheel',
'prepare_metadata_for_build_wheel', 'prepare_metadata_for_build_wheel',
...@@ -51,7 +53,9 @@ class SetupRequirementsError(BaseException): ...@@ -51,7 +53,9 @@ class SetupRequirementsError(BaseException):
class Distribution(setuptools.dist.Distribution): class Distribution(setuptools.dist.Distribution):
def fetch_build_eggs(self, specifiers): def fetch_build_eggs(self, specifiers):
raise SetupRequirementsError(specifiers) specifier_list = self._parse_requirements(specifiers)
raise SetupRequirementsError(specifier_list)
@classmethod @classmethod
@contextlib.contextmanager @contextlib.contextmanager
...@@ -68,6 +72,45 @@ class Distribution(setuptools.dist.Distribution): ...@@ -68,6 +72,45 @@ class Distribution(setuptools.dist.Distribution):
finally: finally:
distutils.core.Distribution = orig distutils.core.Distribution = orig
def _yield_lines(self, strs):
"""Yield non-empty/non-comment lines of a string or sequence"""
if isinstance(strs, six.string_types):
for s in strs.splitlines():
s = s.strip()
# skip blank lines/comments
if s and not s.startswith('#'):
yield s
else:
for ss in strs:
for s in self._yield_lines(ss):
yield s
def _parse_requirements(self, strs):
"""Parse requirement specifiers into a list of requirement strings
This is forked from pkg_resources.parse_requirements.
`strs` must be a string, or a (possibly-nested) iterable thereof.
"""
# create a steppable iterator, so we can handle \-continuations
lines = iter(self._yield_lines(strs))
requirements = []
for line in lines:
# Drop comments -- a hash without a space may be in a URL.
if ' #' in line:
line = line[:line.find(' #')]
# If there is a line continuation, drop it, and append the next line.
if line.endswith('\\'):
line = line[:-2].strip()
try:
line += next(lines)
except StopIteration:
return
requirements.append(line)
return requirements
def _to_str(s): def _to_str(s):
""" """
......
...@@ -288,21 +288,17 @@ class TestBuildMetaBackend: ...@@ -288,21 +288,17 @@ class TestBuildMetaBackend:
build_backend.build_sdist("temp") build_backend.build_sdist("temp")
@pytest.mark.parametrize('setup_literal, requirements', [ @pytest.mark.parametrize('setup_literal, requirements', [
pytest.param("'foo'", ['foo'], marks=pytest.mark.xfail), ("'foo'", ['foo']),
("['foo']", ['foo']), ("['foo']", ['foo']),
pytest.param(r"'foo\n'", ['foo'], marks=pytest.mark.xfail), (r"'foo\n'", ['foo']),
pytest.param(r"'foo\n\n'", ['foo'], marks=pytest.mark.xfail), (r"'foo\n\n'", ['foo']),
("['foo', 'bar']", ['foo', 'bar']), ("['foo', 'bar']", ['foo', 'bar']),
pytest.param(r"'# Has a comment line\nfoo'", (r"'# Has a comment line\nfoo'", ['foo']),
['foo'], marks=pytest.mark.xfail), (r"'foo # Has an inline comment'", ['foo']),
pytest.param(r"'foo # Has an inline comment'", (r"'foo \\\n >=3.0'", ['foo>=3.0']),
['foo'], marks=pytest.mark.xfail), (r"'foo\nbar'", ['foo', 'bar']),
pytest.param(r"'foo \\\n >=3.0'", (r"'foo\nbar\n'", ['foo', 'bar']),
['foo>=3.0'], marks=pytest.mark.xfail), (r"['foo\n', 'bar\n']", ['foo', 'bar']),
pytest.param(r"'foo\nbar'", ['foo', 'bar'], marks=pytest.mark.xfail),
pytest.param(r"'foo\nbar\n'", ['foo', 'bar'], marks=pytest.mark.xfail),
pytest.param(r"['foo\n', 'bar\n']",
['foo', 'bar'], marks=pytest.mark.xfail),
]) ])
def test_setup_requires(self, setup_literal, requirements, tmpdir_cwd): def test_setup_requires(self, setup_literal, requirements, tmpdir_cwd):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment