Allow requirements_in to be generated (#829)
* Allow requirements_in to be generated
We generate the `requirements_in` file from various input files
roughly like so:
genrule(
name = "generate_3.7_x86_requirements",
srcs = [
"requirements_base.in.txt",
"requirements_extra_37.in.txt",
],
outs = ["requirements_3.7_x86.txt"],
cmd = "cat $(SRCS) > $(OUTS)",
)
compile_pip_requirements(
name = "compile_requirements_3.7_x86",
requirements_in = ":requirements_3.7_x86.txt",
requirements_txt = "requirements_3.7_x86.lock.txt",
)
The current code errors out with a message like this:
Updating common/python/requirements_3.7_x86.lock.txt
Usage: pip_compile.py [OPTIONS] [SRC_FILES]...
Try 'pip_compile.py -h' for help.
Error: Invalid value for '[SRC_FILES]...': Path 'common/python/requirements_3.7_x86.txt' does not exist.
This patch here fixes the issue by resolving the `requirements_in`
path before the tool `cd`s into the workspace directory.
* Make tests pass
* Run black
* Fix some runtime problems
Co-authored-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com>diff --git a/examples/pip_parse/BUILD b/examples/pip_parse/BUILD
index 653f75c..1b6ba55 100644
--- a/examples/pip_parse/BUILD
+++ b/examples/pip_parse/BUILD
@@ -55,6 +55,16 @@
actual = entry_point("yamllint"),
)
+# The requirements.in file can be checked in to the source tree or it can be
+# generated. Pretend that we do some generating of the file. For this example,
+# the "template" is already the file we want.
+genrule(
+ name = "generate_requirements_in",
+ srcs = ["requirements.in.template"],
+ outs = ["requirements.in"],
+ cmd = "cp $(SRCS) $(OUTS)",
+)
+
# This rule adds a convenient way to update the requirements file.
compile_pip_requirements(
name = "requirements",
diff --git a/examples/pip_parse/requirements.in b/examples/pip_parse/requirements.in.template
similarity index 100%
rename from examples/pip_parse/requirements.in
rename to examples/pip_parse/requirements.in.template
diff --git a/python/pip_install/pip_compile.py b/python/pip_install/pip_compile.py
index 9258c17..c9bcf32 100644
--- a/python/pip_install/pip_compile.py
+++ b/python/pip_install/pip_compile.py
@@ -2,6 +2,7 @@
import os
import sys
+from pathlib import Path
from shutil import copyfile
from piptools.scripts.compile import cli
@@ -25,6 +26,21 @@
return requirements_txt
+def _fix_up_requirements_in_path(
+ resolved_requirements_in, requirements_in, output_file
+):
+ """Fix up references to the input file inside of the generated requirements file.
+
+ We don't want fully resolved, absolute paths in the generated requirements file.
+ The paths could differ for every invocation. Replace them with a predictable path.
+ """
+ output_file = Path(output_file)
+ fixed_requirements_text = output_file.read_text().replace(
+ resolved_requirements_in, requirements_in
+ )
+ output_file.write_text(fixed_requirements_text)
+
+
if __name__ == "__main__":
if len(sys.argv) < 4:
print(
@@ -42,6 +58,10 @@
requirements_windows = parse_str_none(sys.argv.pop(1))
update_target_label = sys.argv.pop(1)
+ # The requirements_in file could be generated. We need to get the path to it before we change
+ # directory into the workspace directory.
+ resolved_requirements_in = str(Path(requirements_in).resolve())
+
# Before loading click, set the locale for its parser.
# If it leaks through to the system setting, it may fail:
# RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII
@@ -96,11 +116,18 @@
sys.argv.append("--generate-hashes")
sys.argv.append("--output-file")
sys.argv.append(requirements_txt if UPDATE else requirements_out)
- sys.argv.append(requirements_in)
+ sys.argv.append(resolved_requirements_in)
if UPDATE:
print("Updating " + requirements_txt)
- cli()
+ try:
+ cli()
+ except SystemExit as e:
+ if e.code == 0:
+ _fix_up_requirements_in_path(
+ resolved_requirements_in, requirements_in, requirements_txt
+ )
+ raise
else:
# cli will exit(0) on success
try:
@@ -118,6 +145,9 @@
)
sys.exit(1)
elif e.code == 0:
+ _fix_up_requirements_in_path(
+ resolved_requirements_in, requirements_in, requirements_out
+ )
golden_filename = _select_golden_requirements_file(
requirements_txt,
requirements_linux,