From e84d7436b134c433efc9ea35082606cf7ad7dd30 Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Fri, 24 Jul 2026 22:32:27 -0700 Subject: [PATCH] Make pip-sync honor src_files from the config file pip-compile reads src_files out of the click context default_map when none are given on the command line, but pip-sync never did, so [tool.pip-tools.sync] src_files was silently ignored and pip-sync always fell back to requirements.txt (or exited 2 when it was absent). Apply the same default_map lookup in pip-sync. CLI arguments still win. Fixes #2187 --- changelog.d/2187.bugfix.md | 1 + piptools/scripts/sync.py | 8 ++++++++ tests/test_cli_sync.py | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 changelog.d/2187.bugfix.md diff --git a/changelog.d/2187.bugfix.md b/changelog.d/2187.bugfix.md new file mode 100644 index 000000000..5abcc099f --- /dev/null +++ b/changelog.d/2187.bugfix.md @@ -0,0 +1 @@ +Made `pip-sync` respect `src_files` set in the config file, matching `pip-compile` -- by {user}`Sanjays2402`. diff --git a/piptools/scripts/sync.py b/piptools/scripts/sync.py index 877d58a05..3525ce809 100755 --- a/piptools/scripts/sync.py +++ b/piptools/scripts/sync.py @@ -48,6 +48,7 @@ @click.command(name="pip-sync") +@click.pass_context @options.help_option(epilog=SYNC_EPILOG) @options.version @options.ask @@ -69,6 +70,7 @@ @options.config @options.no_config def cli( + ctx: click.Context, ask: bool, dry_run: bool, force: bool, @@ -91,6 +93,12 @@ def cli( """Synchronize virtual environment with requirements.txt.""" log.verbosity = verbose - quiet + # If ``src_files`` was not provided as an input, but rather as config, + # it will be part of the click context ``ctx``. + # However, if ``src_files`` is specified, then we want to use that. + if not src_files and ctx.default_map and "src_files" in ctx.default_map: + src_files = tuple(ctx.default_map["src_files"]) + if not src_files: if os.path.exists(DEFAULT_REQUIREMENTS_FILE): src_files = (DEFAULT_REQUIREMENTS_FILE,) diff --git a/tests/test_cli_sync.py b/tests/test_cli_sync.py index a07f97309..b1cf8d6c9 100644 --- a/tests/test_cli_sync.py +++ b/tests/test_cli_sync.py @@ -488,3 +488,43 @@ def test_tool_specific_config_option(run, runner, make_config_file): assert out.exit_code == 1 assert "Would install:" in out.stdout + + +@mock.patch("piptools.sync.run") +def test_use_src_files_from_config_if_option_is_not_specified_from_cli( + run, runner, make_config_file +): + config_file = make_config_file( + "src-files", ["requirements_lock.txt"], section="pip-tools", subsection="sync" + ) + + with open("requirements_lock.txt", "w") as reqs_txt: + reqs_txt.write("six==1.10.0") + + out = runner.invoke(cli, ["--dry-run", "--config", config_file.as_posix()]) + + assert out.exit_code == 1 + assert "Would install:" in out.stdout + assert "six==1.10.0" in out.stdout + + +@mock.patch("piptools.sync.run") +def test_use_src_files_from_cli_if_option_is_specified_in_both_config_and_cli( + run, runner, make_config_file +): + config_file = make_config_file( + "src-files", ["requirements_lock.txt"], section="pip-tools", subsection="sync" + ) + + with open("requirements_lock.txt", "w") as reqs_txt: + reqs_txt.write("six==1.10.0") + with open("other.txt", "w") as reqs_txt: + reqs_txt.write("small-fake-a==0.1") + + out = runner.invoke( + cli, ["other.txt", "--dry-run", "--config", config_file.as_posix()] + ) + + assert out.exit_code == 1 + assert "small-fake-a==0.1" in out.stdout + assert "six==1.10.0" not in out.stdout