diff --git a/src/pip_deepfreeze/req_merge.py b/src/pip_deepfreeze/req_merge.py index 77888a6..60744c1 100644 --- a/src/pip_deepfreeze/req_merge.py +++ b/src/pip_deepfreeze/req_merge.py @@ -1,10 +1,9 @@ -import shlex from pathlib import Path from typing import Iterable, Iterator, Optional from packaging.utils import canonicalize_name -from .req_file_parser import OptionsLine, RequirementLine, parse +from .req_file_parser import OptionsLine, ParsedLine, RequirementLine, parse from .req_parser import get_req_name from .utils import HttpFetcher, log_error @@ -14,13 +13,15 @@ def prepare_frozen_reqs_for_upgrade( constraints_path: Path, upgrade_all: bool = False, to_upgrade: Optional[Iterable[str]] = None, -) -> Iterator[str]: +) -> Iterator[ParsedLine]: """Merge frozen requirements and constraints. pip options are taken from the constraints file. All frozen requirements are preserved, unless an upgrade is explicitly requested via ``upgrade_all`` or ``to_upgrade``. Other constraints not in frozen requirements are added. + + Yield tuples of (req_line, is_option). """ to_upgrade_set = {canonicalize_name(r) for r in to_upgrade or []} constraints_reqs = [] @@ -35,7 +36,7 @@ def prepare_frozen_reqs_for_upgrade( http_fetcher=HttpFetcher(), ): if isinstance(constraint_req, OptionsLine): - yield shlex.join(constraint_req.options) + yield constraint_req elif isinstance(constraint_req, RequirementLine): constraint_req_name = get_req_name(constraint_req.requirement) if not constraint_req_name: @@ -60,8 +61,8 @@ def prepare_frozen_reqs_for_upgrade( if constraint_req_name in to_upgrade_set: continue frozen_reqs_names.add(constraint_req_name) - yield frozen_req.raw_line + yield frozen_req # 3. emit constraints requirements that have not been emitted as frozen reqs for constraint_req_name, constraint_req in constraints_reqs: if constraint_req_name not in frozen_reqs_names: - yield constraint_req.raw_line + yield constraint_req diff --git a/src/pip_deepfreeze/sync.py b/src/pip_deepfreeze/sync.py index a0213f4..fd8784c 100644 --- a/src/pip_deepfreeze/sync.py +++ b/src/pip_deepfreeze/sync.py @@ -53,6 +53,7 @@ def sync( merged_constraints_path = get_temp_path_in_dir( dir=project_root, prefix="requirements.", suffix=".txt.df" ) + installer_options = [] with merged_constraints_path.open(mode="w", encoding="utf-8") as constraints: for req_line in prepare_frozen_reqs_for_upgrade( make_frozen_requirements_paths(project_root, extras), @@ -60,13 +61,17 @@ def sync( upgrade_all, to_upgrade, ): - print(req_line, file=constraints) + if isinstance(req_line, OptionsLine): + installer_options.extend(req_line.options) + else: + print(req_line.raw_line, file=constraints) pip_upgrade_project( python, merged_constraints_path, project_root, extras=extras, installer=installer, + installer_options=installer_options, ) # freeze dependencies frozen_reqs_by_extra, unneeded_reqs = pip_freeze_dependencies_by_extra( @@ -90,8 +95,8 @@ def sync( print(parsed_req_line.raw_line, file=f) # output frozen dependencies of project, # sorted by canonical requirement name - for req_line in sorted(frozen_reqs, key=_req_line_sort_key): - print(normalize_req_line(req_line), file=f) + for frozen_req in sorted(frozen_reqs, key=_req_line_sort_key): + print(normalize_req_line(frozen_req), file=f) # uninstall unneeded dependencies, if asked to do so unneeded_req_names = sorted( set(str(s) for s in get_req_names(unneeded_reqs)) diff --git a/tests/test_req_merge.py b/tests/test_req_merge.py index 7aae359..a79b4d0 100644 --- a/tests/test_req_merge.py +++ b/tests/test_req_merge.py @@ -51,7 +51,8 @@ def test_merge(in_reqs, frozen_reqs, upgrade_all, to_upgrade, expected, tmp_path frozen_filename.write_text("\n".join(frozen_reqs)) assert ( set( - prepare_frozen_reqs_for_upgrade( + r.raw_line + for r in prepare_frozen_reqs_for_upgrade( [frozen_filename], constraints_filename, upgrade_all, to_upgrade ) ) @@ -64,7 +65,10 @@ def test_merge_missing_in(tmp_path): frozen_filename = tmp_path / "requirements.txt" frozen_filename.write_text("pkga==1.0.0") assert set( - prepare_frozen_reqs_for_upgrade([frozen_filename], constraints_filename) + r.raw_line + for r in prepare_frozen_reqs_for_upgrade( + [frozen_filename], constraints_filename + ) ) == {"pkga==1.0.0"} @@ -73,7 +77,10 @@ def test_merge_missing_frozen(tmp_path): constraints_filename.write_text("pkga") frozen_filename = tmp_path / "requirements.txt" assert set( - prepare_frozen_reqs_for_upgrade([frozen_filename], constraints_filename) + r.raw_line + for r in prepare_frozen_reqs_for_upgrade( + [frozen_filename], constraints_filename + ) ) == {"pkga"} @@ -94,7 +101,12 @@ def test_req_merge_unnamed_frozen(tmp_path, capsys): frozen_filename = tmp_path / "requirements.txt" frozen_filename.write_text("-e .") assert ( - set(prepare_frozen_reqs_for_upgrade([frozen_filename], constraints_filename)) + set( + r.raw_line + for r in prepare_frozen_reqs_for_upgrade( + [frozen_filename], constraints_filename + ) + ) == set() ) captured = capsys.readouterr() @@ -108,5 +120,8 @@ def test_req_merge_named_editable(tmp_path): ) frozen_filename = tmp_path / "requirements.txt" assert set( - prepare_frozen_reqs_for_upgrade([frozen_filename], constraints_filename) - ) == set(["-e git+https://github.com/pypa/pip-test-package#egg=pip-test-package"]) + r.raw_line + for r in prepare_frozen_reqs_for_upgrade( + [frozen_filename], constraints_filename + ) + ) == {"-e git+https://github.com/pypa/pip-test-package#egg=pip-test-package"}