Skip to main content

python/pip_compile

1#!/usr/bin/env python3
2"""
3Compile any `requirements.in` files into a list of exact versions
4in `requirements.txt`.
6* If you pass the `--upgrade` flag, it will upgrade all the requirements
7 to the latest version.
9"""
11from pathlib import Path
12import shlex
13import subprocess
14import sys
17def compile_requirements_file(in_file: str, *, upgrade: bool, no_cache: bool) -> None:
18 """
19 Compile a single requirements file.
20 """
21 assert in_file.endswith(".in")
22 txt_file = in_file.replace(".in", ".txt")
23 assert in_file != txt_file
25 # If this `.in` file doesn't exist.
26 if not Path(in_file).exists():
27 return
29 # Construct the `uv pip compile` command.
30 cmd = [
31 "uv",
32 "pip",
33 "compile",
34 in_file,
35 f"--output-file={txt_file}",
36 #
37 # Exclude dependencies which are less than 7 days old; this is
38 # a mitigation against supply chain attacks and installing
39 # recently-published malicious code on my computer.
40 "--exclude-newer=P7D",
41 #
42 # Allow installing new versions of my own packages
43 "--exclude-newer-package", "alexwlchan-chives=false",
44 ]
46 if upgrade:
47 cmd.append("--upgrade")
49 if no_cache:
50 cmd.append("--no-cache")
52 # Actually run the command, and print a debug entry for it.
53 #
54 # `uv pip compile` prints the generated `requirements.txt` file to
55 # stdout, so we pipe that to /dev/null -- we're writing it to a file.
56 subprocess.check_call(
57 ["/Users/alexwlchan/repos/scripts/debug/print_info", f"-> {shlex.join(cmd)}"]
58 )
59 subprocess.check_call(cmd, stdout=subprocess.DEVNULL)
62if __name__ == "__main__":
63 for f in ["requirements.in", "dev_requirements.in"]:
64 compile_requirements_file(
65 f, upgrade="--upgrade" in sys.argv, no_cache="--no-cache" in sys.argv
66 )