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

Allow build deps as long as at least one setup file is in sources list. #2077

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
14 changes: 7 additions & 7 deletions piptools/scripts/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,13 +332,6 @@ def cli(
setup_file_found = False
for src_file in src_files:
is_setup_file = os.path.basename(src_file) in METADATA_FILENAMES
if not is_setup_file and build_deps_targets:
msg = (
"--build-deps-for and --all-build-deps can be used only with the "
"setup.py, setup.cfg and pyproject.toml specs."
)
raise click.BadParameter(msg)

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
Expand Down Expand Up @@ -430,6 +423,13 @@ def cli(
msg = "--extra has effect only with setup.py and PEP-517 input formats"
raise click.BadParameter(msg)

if build_deps_targets and not setup_file_found:
msg = (
"--build-deps-for and --all-build-deps can be used only with the "
"setup.py, setup.cfg and pyproject.toml specs."
)
raise click.BadParameter(msg)

primary_packages = {
key_from_ireq(ireq) for ireq in constraints if not ireq.constraint
}
Expand Down
98 changes: 98 additions & 0 deletions tests/test_cli_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2964,6 +2964,104 @@ def test_build_deps_fail_without_setup_file(runner, tmpdir, option):
assert exp in out.stderr


@backtracking_resolver_only
@pytest.mark.parametrize("option", ("--all-build-deps", "--build-deps-for=wheel"))
def test_build_deps_does_not_error_when_setup_included_with_multiple_source_files(
fake_dists_with_build_deps,
runner,
tmp_path,
monkeypatch,
current_resolver,
option,
):
"""
Test that passing ``--build-deps-for`` or ``--all-build-deps`` does not emit an
error as long as at least one file in the sources list is a setup file.
"""
src_pkg_path = pathlib.Path(PACKAGES_PATH) / "small_fake_with_build_deps"
# When used as argument to the runner it is not passed to pip
monkeypatch.setenv("PIP_FIND_LINKS", fake_dists_with_build_deps)

requirements_path = pathlib.Path(tmp_path) / "requirements.in"
requirements_path.write_text("\n")

pyproject_toml_path = pathlib.Path(tmp_path) / "pyproject.toml"
pyproject_toml_path.write_text("\n")

with runner.isolated_filesystem(tmp_path) as tmp_pkg_path:
shutil.copytree(src_pkg_path, tmp_pkg_path, dirs_exist_ok=True)
out = runner.invoke(
cli,
[
"--allow-unsafe",
"--output-file",
"-",
"--quiet",
"--no-emit-options",
"--no-header",
option,
os.fspath(requirements_path),
os.fspath(pyproject_toml_path),
],
)

exp = (
"--build-deps-for and --all-build-deps can be used only with the "
"setup.py, setup.cfg and pyproject.toml specs."
)
assert exp not in out.stderr
assert out.exit_code == 0


@backtracking_resolver_only
@pytest.mark.parametrize("option", ("--all-build-deps", "--build-deps-for=wheel"))
def test_build_deps_does_not_error_when_multiple_setup_included_in_source_files(
fake_dists_with_build_deps,
runner,
tmp_path,
monkeypatch,
current_resolver,
option,
):
"""
Test that passing ``--build-deps-for`` or ``--all-build-deps`` does not emit an
error as long when multiple setup files are included in the source files list.
"""
src_pkg_path = pathlib.Path(PACKAGES_PATH) / "small_fake_with_build_deps"
# When used as argument to the runner it is not passed to pip
monkeypatch.setenv("PIP_FIND_LINKS", fake_dists_with_build_deps)

pyproject_toml_path = pathlib.Path(tmp_path) / "pyproject.toml"
pyproject_toml_path.write_text("\n")

pyproject_toml_2_path = pathlib.Path(tmp_path) / "pyproject.toml"
pyproject_toml_2_path.write_text("\n")

with runner.isolated_filesystem(tmp_path) as tmp_pkg_path:
shutil.copytree(src_pkg_path, tmp_pkg_path, dirs_exist_ok=True)
out = runner.invoke(
cli,
[
"--allow-unsafe",
"--output-file",
"-",
"--quiet",
"--no-emit-options",
"--no-header",
option,
os.fspath(pyproject_toml_path),
os.fspath(pyproject_toml_2_path),
],
)

exp = (
"--build-deps-for and --all-build-deps can be used only with the "
"setup.py, setup.cfg and pyproject.toml specs."
)
assert exp not in out.stderr
assert out.exit_code == 0


def test_extras_fail_with_requirements_in(runner, tmpdir):
"""
Test that passing ``--extra`` with ``requirements.in`` input file fails.
Expand Down