Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace direct usage of the pep517 module with the build module, for loading project metadata #1629

Merged
merged 7 commits into from Jun 15, 2022
16 changes: 12 additions & 4 deletions piptools/scripts/compile.py
Expand Up @@ -6,8 +6,9 @@
from typing import IO, Any, BinaryIO, List, Optional, Tuple, Union, cast

import click
from build import BuildBackendException
from build.util import project_wheel_metadata
from click.utils import LazyFile, safecall
from pep517 import meta
from pip._internal.commands import create_command
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
Expand Down Expand Up @@ -405,12 +406,19 @@ def cli(
constraints.extend(reqs)
elif is_setup_file:
setup_file_found = True
dist = meta.load(os.path.dirname(os.path.abspath(src_file)))
comes_from = f"{dist.metadata.get_all('Name')[0]} ({src_file})"
try:
metadata = project_wheel_metadata(
os.path.dirname(os.path.abspath(src_file))
)
except BuildBackendException as e:
log.error(str(e))
log.error(f"Failed to parse {os.path.abspath(src_file)}")
sys.exit(2)
comes_from = f"{metadata.get_all('Name')[0]} ({src_file})"
constraints.extend(
[
install_req_from_line(req, comes_from=comes_from)
for req in dist.requires or []
for req in metadata.get_all("Requires-Dist") or []
]
)
else:
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Expand Up @@ -30,8 +30,8 @@ packages = find:
zip_safe = false
install_requires =
# direct dependencies
build
click >= 7
pep517
pip >= 21.2
# indirect dependencies
setuptools # typically needed when pip-tools invokes setup.py
Expand Down
12 changes: 12 additions & 0 deletions tests/conftest.py
Expand Up @@ -349,6 +349,18 @@ def _make_module(fname, content):
path = os.path.join(tmpdir, "sample_lib", "__init__.py")
with open(path, "w") as stream:
stream.write("'example module'\n__version__ = '1.2.3'")
if fname == "setup.cfg":
path = os.path.join(tmpdir, "pyproject.toml")
with open(path, "w") as stream:
stream.write(
"\n".join(
(
"[build-system]",
'requires = ["setuptools"]',
'build-backend = "setuptools.build_meta"',
)
)
)
path = os.path.join(tmpdir, fname)
with open(path, "w") as stream:
stream.write(dedent(content))
Expand Down
19 changes: 10 additions & 9 deletions tests/test_cli_compile.py
Expand Up @@ -12,9 +12,6 @@

from .constants import MINIMAL_WHEELS_PATH, PACKAGES_PATH

is_pypy = "__pypy__" in sys.builtin_module_names
is_windows = sys.platform == "win32"


@pytest.fixture(autouse=True)
def _temp_dep_cache(tmpdir, monkeypatch):
Expand Down Expand Up @@ -349,9 +346,6 @@ def test_emit_index_url_option(runner, option, expected_output):


@pytest.mark.network
@pytest.mark.xfail(
is_pypy and is_windows, reason="https://github.com/jazzband/pip-tools/issues/1148"
)
def test_realistic_complex_sub_dependencies(runner):
wheels_dir = "wheels"

Expand Down Expand Up @@ -1017,6 +1011,16 @@ def test_filter_pip_markers(pip_conf, runner):
assert "unknown_package" not in out.stderr


def test_bad_setup_file(runner):
with open("setup.py", "w") as package:
package.write("BAD SYNTAX")

out = runner.invoke(cli, [])

assert out.exit_code == 2
assert f"Failed to parse {os.path.abspath('setup.py')}" in out.stderr


def test_no_candidates(pip_conf, runner):
with open("requirements", "w") as req_in:
req_in.write("small-fake-a>0.3b1,<0.3b2")
Expand Down Expand Up @@ -2027,7 +2031,6 @@ def test_triple_equal_pinned_dependency_is_used(

@pytest.mark.network
@pytest.mark.parametrize(("fname", "content"), METADATA_TEST_CASES)
@pytest.mark.xfail(is_pypy, reason="https://github.com/jazzband/pip-tools/issues/1375")
def test_input_formats(fake_dists, runner, make_module, fname, content):
"""
Test different dependency formats as input file.
Expand All @@ -2046,7 +2049,6 @@ def test_input_formats(fake_dists, runner, make_module, fname, content):

@pytest.mark.network
@pytest.mark.parametrize(("fname", "content"), METADATA_TEST_CASES)
@pytest.mark.xfail(is_pypy, reason="https://github.com/jazzband/pip-tools/issues/1375")
def test_one_extra(fake_dists, runner, make_module, fname, content):
"""
Test one `--extra` (dev) passed, other extras (test) must be ignored.
Expand Down Expand Up @@ -2074,7 +2076,6 @@ def test_one_extra(fake_dists, runner, make_module, fname, content):
),
)
@pytest.mark.parametrize(("fname", "content"), METADATA_TEST_CASES)
@pytest.mark.xfail(is_pypy, reason="https://github.com/jazzband/pip-tools/issues/1375")
def test_multiple_extras(fake_dists, runner, make_module, fname, content, extra_opts):
"""
Test passing multiple `--extra` params.
Expand Down