-
Notifications
You must be signed in to change notification settings - Fork 83
Expand file tree
/
Copy pathcheck_requirements.py
More file actions
executable file
·86 lines (76 loc) · 3.35 KB
/
check_requirements.py
File metadata and controls
executable file
·86 lines (76 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# WARNING: DO NOT EDIT!
#
# This file was generated by plugin_template, and is managed by it. Please use
# './plugin-template --github pulp_python' to update this file.
#
# For more info visit https://github.com/pulp/plugin_template
import tomllib
import warnings
from packaging.requirements import Requirement
CHECK_MATRIX = [
("pyproject.toml", True, True, True),
("requirements.txt", True, True, True),
("dev_requirements.txt", False, True, False),
("ci_requirements.txt", False, True, True),
("doc_requirements.txt", False, True, False),
("lint_requirements.txt", False, True, True),
("unittest_requirements.txt", False, True, True),
("functest_requirements.txt", False, True, True),
("clitest_requirements.txt", False, True, True),
]
def iterate_file(filename):
if filename == "pyproject.toml":
with open(filename, "rb") as fd:
pyproject_toml = tomllib.load(fd)
if "project" in pyproject_toml:
for nr, line in enumerate(pyproject_toml["project"]["dependencies"]):
yield nr, line
else:
with open(filename, "r") as fd:
for nr, line in enumerate(fd.readlines()):
line = line.strip()
if not line or line.startswith("#"):
continue
if "#" in line:
line = line.split("#", maxsplit=1)[0]
yield nr, line.strip()
def main():
errors = []
for filename, check_upperbound, check_prereleases, check_r in CHECK_MATRIX:
try:
for nr, line in iterate_file(filename):
try:
req = Requirement(line)
except ValueError:
if line.startswith("git+"):
# The single exception...
if "pulp-smash" not in line:
errors.append(f"{filename}:{nr}: Invalid source requirement: {line}")
elif line.startswith("-r "):
if check_r:
errors.append(f"{filename}:{nr}: Invalid deferred requirement: {line}")
else:
errors.append(f"{filename}:{nr}: Unreadable requirement {line}")
else:
if check_prereleases and req.specifier.prereleases:
# Do not even think about begging for more exceptions!
if (
not req.name.startswith("opentelemetry")
and req.name != "pulp-python-client"
):
errors.append(f"{filename}:{nr}: Prerelease versions found in {line}.")
ops = [spec.operator for spec in req.specifier]
if "~=" in ops:
warnings.warn(f"{filename}:{nr}: Please avoid using ~= on {req.name}!")
elif "<" not in ops and "<=" not in ops and "==" not in ops:
if check_upperbound:
errors.append(f"{filename}:{nr}: Upper bound missing in {line}.")
except FileNotFoundError:
# skip this test for plugins that don't use this requirements.txt
pass
if errors:
print("Dependency issues found:")
print("\n".join(errors))
exit(1)
if __name__ == "__main__":
main()