Coverage for src/iso_freeze/pin_requirements.py: 80%
25 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-08-01 11:38 +0200
« prev ^ index » next coverage.py v6.4.2, created at 2022-08-01 11:38 +0200
1"""Write *requirements.txt file."""
3from pathlib import Path
5from iso_freeze.lib import PyPackage
8def pin_requirements(
9 requirements: list[PyPackage], hashes: bool, output_file: Path
10) -> None:
11 """Write *requirements.txt file.
13 Arguments:
14 requirements -- List of packages to pin (list[PyPackage])
15 hashes -- Whether to include hashes (bool)
16 output_file -- Path to file that should be created (Path)
17 """
18 output_file_contents: list[str] = build_reqirements_file_contents(
19 requirements=requirements, hashes=hashes
20 )
21 write_requirements_file(output_file=output_file, file_contents=output_file_contents)
22 print(f"Pinned specified requirements in {output_file}")
25def build_reqirements_file_contents(
26 requirements: list[PyPackage], hashes: bool
27) -> list[str]:
28 """Build contents of requirements file as a list.
30 Display top level dependencies on top, similar to pip freeze -r requirements_file.
32 Arguments:
33 requirements -- Dependencies listed in pip install --report (list[dict[str]])
34 hashes -- Whether to include hashes (bool)
36 Returns:
37 Contents of requirements file (list[str])
38 """
39 # For easier formatting we create separate lists for top level requirements
40 # and their dependencies
41 top_level_requirements: list[str] = []
42 dependency_requirements: list[str] = []
43 for package in requirements:
44 pinned_format: str = f"{package.name}=={package.version}"
45 if hashes:
46 pinned_format += f" \\\n --hash={package.hash}"
47 # If requested == True, the package is a top level requirement
48 if package.requested:
49 top_level_requirements.append(pinned_format)
50 else:
51 dependency_requirements.append(pinned_format)
52 # Sort pinned packages alphabetically before writing to file
53 # (case-insensitively thanks to key=str.lower)
54 top_level_requirements.sort(key=str.lower)
55 # Combine lists and add comments
56 requirements_file_content: list[str] = [
57 "# Top level requirements",
58 *top_level_requirements,
59 ]
60 if dependency_requirements:
61 dependency_requirements.sort(key=str.lower)
62 requirements_file_content.extend(
63 ["# Dependencies of top level requirements", *dependency_requirements]
64 )
65 return requirements_file_content
68def write_requirements_file(output_file: Path, file_contents: list[str]) -> None:
69 """Write requirements file.
71 Arguments:
72 output_file -- Path to and name of requirements.txt file (Path)
73 file_contents -- Contents to to written to a file (list[str])
74 """
75 with output_file.open(mode="w", encoding="utf=8") as f:
76 f.writelines(f"{package}\n" for package in file_contents)