diff --git a/piptools/scripts/compile.py b/piptools/scripts/compile.py index 94ab2358f..1d74616a7 100755 --- a/piptools/scripts/compile.py +++ b/piptools/scripts/compile.py @@ -6,8 +6,12 @@ import click from click.utils import safecall +from pep517 import meta from pip._internal.commands import create_command -from pip._internal.req.constructors import install_req_from_line +from pip._internal.req.constructors import ( + install_req_from_line, + install_req_from_req_string, +) from pip._internal.utils.misc import redact_auth_from_url from .._compat import parse_requirements @@ -330,21 +334,14 @@ def cli( constraints = [] for src_file in src_files: is_setup_file = os.path.basename(src_file) == "setup.py" - if is_setup_file or src_file == "-": + if src_file == "-": # pip requires filenames and not files. Since we want to support # piping from stdin, we need to briefly save the input from stdin # to a temporary file and have pip read that. also used for # reading requirements from install_requires in setup.py. tmpfile = tempfile.NamedTemporaryFile(mode="wt", delete=False) - if is_setup_file: - from distutils.core import run_setup - - dist = run_setup(src_file) - tmpfile.write("\n".join(dist.install_requires)) - comes_from = f"{dist.get_name()} ({src_file})" - else: - tmpfile.write(sys.stdin.read()) - comes_from = "-r -" + tmpfile.write(sys.stdin.read()) + comes_from = "-r -" tmpfile.flush() reqs = list( parse_requirements( @@ -357,6 +354,15 @@ def cli( for req in reqs: req.comes_from = comes_from constraints.extend(reqs) + elif is_setup_file: + dist = meta.load(".") + comes_from = f"{dist.metadata.get_all('Name')[0]} ({src_file})" + constraints.extend( + [ + install_req_from_req_string(req, comes_from=comes_from) + for req in dist.requires or [] + ] + ) else: constraints.extend( parse_requirements( @@ -378,7 +384,9 @@ def cli( # Filter out pip environment markers which do not match (PEP496) constraints = [ - req for req in constraints if req.markers is None or req.markers.evaluate() + req + for req in constraints + if req.markers is None or req.markers.evaluate(dict(extra=None)) ] log.debug("Using indexes:") diff --git a/setup.cfg b/setup.cfg index 521c4215b..ed6e28cb8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,6 +30,7 @@ packages = find: zip_safe = false install_requires = click >= 7 + pep517 pip >= 20.1 [options.packages.find] diff --git a/tests/test_cli_compile.py b/tests/test_cli_compile.py index f893ab737..12e48cb7b 100644 --- a/tests/test_cli_compile.py +++ b/tests/test_cli_compile.py @@ -38,7 +38,17 @@ def test_command_line_overrides_pip_conf(pip_with_index_conf, runner): assert "Using indexes:\n http://override.com" in out.stderr -def test_command_line_setuptools_read(pip_conf, runner): +def test_command_line_setuptools_read(make_pip_conf, runner): + make_pip_conf( + dedent( + f"""\ + [global] + disable-pip-version-check = True + find-links = {MINIMAL_WHEELS_PATH} + """ + ) + ) + with open("setup.py", "w") as package: package.write( dedent( @@ -86,11 +96,20 @@ def test_command_line_setuptools_read(pip_conf, runner): ), ) def test_command_line_setuptools_output_file( - pip_conf, runner, options, expected_output_file + make_pip_conf, runner, options, expected_output_file ): """ Test the output files for setup.py as a requirement file. """ + make_pip_conf( + dedent( + f"""\ + [global] + find-links = {MINIMAL_WHEELS_PATH} + """ + ) + ) + with open("setup.py", "w") as package: package.write( dedent(