-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
215 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import subprocess | ||
from pathlib import Path | ||
from typing import Iterator, List, Optional, Sequence | ||
|
||
from packaging.utils import NormalizedName | ||
|
||
from .installed_dist import installed_distributions_as_pip_requirements | ||
from .pip import ( | ||
_dependencies_by_extra, # TODO _dependencies_by_extra should be elsewhere | ||
pip_dry_run_install_project, | ||
) | ||
from .project_name import get_project_name | ||
from .req_file_parser import OptionsLine, parse as parse_req_file | ||
from .req_merge import prepare_frozen_reqs_for_upgrade | ||
from .utils import ( | ||
HttpFetcher, | ||
get_temp_path_in_dir, | ||
log_info, | ||
open_with_rollback, | ||
) | ||
|
||
|
||
def _make_requirements_path(project_root: Path, extra: Optional[str]) -> Path: | ||
if extra: | ||
return project_root / f"requirements-{extra}.txt" | ||
else: | ||
return project_root / "requirements.txt" | ||
|
||
|
||
def _make_requirements_paths( | ||
project_root: Path, extras: Sequence[str] | ||
) -> Iterator[Path]: | ||
yield _make_requirements_path(project_root, None) | ||
for extra in extras: | ||
yield _make_requirements_path(project_root, extra) | ||
|
||
|
||
def lock( | ||
python: str, | ||
upgrade_all: bool, | ||
to_upgrade: List[str], | ||
extras: List[NormalizedName], | ||
project_root: Path, | ||
post_lock_commands: Sequence[str] = (), | ||
) -> None: | ||
project_name = get_project_name(python, project_root) | ||
requirements_in = project_root / "requirements.txt.in" | ||
# upgrade project and its dependencies, if needed | ||
constraints_path = get_temp_path_in_dir( | ||
dir=project_root, prefix="requirements.", suffix=".txt.df" | ||
) | ||
with constraints_path.open(mode="w", encoding="utf-8") as constraints: | ||
for req_line in prepare_frozen_reqs_for_upgrade( | ||
_make_requirements_paths(project_root, extras), | ||
requirements_in, | ||
upgrade_all, | ||
to_upgrade, | ||
): | ||
print(req_line, file=constraints) | ||
installed_distributions = pip_dry_run_install_project( | ||
python, | ||
constraints_path, | ||
project_root, | ||
extras=extras, | ||
) | ||
# freeze dependencies | ||
# TODO _dependencies_by_extra should be elsewhere | ||
frozen_reqs_by_extra, unneeded_reqs = _dependencies_by_extra( | ||
project_name, | ||
extras, | ||
installed_distributions, | ||
installed_distributions_as_pip_requirements(installed_distributions), | ||
) | ||
assert not unneeded_reqs | ||
for extra, frozen_reqs in frozen_reqs_by_extra.items(): | ||
requirements_frozen_path = _make_requirements_path(project_root, extra) | ||
with open_with_rollback(requirements_frozen_path) as f: | ||
print("# frozen requirements generated by pip-deepfreeze", file=f) | ||
# output pip options in main requirements only | ||
if not extra and requirements_in.exists(): | ||
# XXX can we avoid this second parse of requirements.txt.in? | ||
for parsed_req_line in parse_req_file( | ||
str(requirements_in), | ||
reqs_only=False, | ||
recurse=True, | ||
strict=True, | ||
http_fetcher=HttpFetcher(), | ||
): | ||
if isinstance(parsed_req_line, OptionsLine): | ||
print(parsed_req_line.raw_line, file=f) | ||
# output frozen dependencies of project | ||
for req_line in frozen_reqs: | ||
print(req_line, file=f) | ||
# run post-lock commands | ||
for command in post_lock_commands: | ||
log_info(f"Running post-lock command: {command}") | ||
result = subprocess.run(command, shell=True, check=False) | ||
if result.returncode != 0: | ||
raise SystemExit( | ||
f"Post-lock command {command} failed with exit code {result.returncode}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters