Skip to content

Commit b294a4a

Browse files
authored
Merge pull request #790 from tiran/optional-resolve-requirements
feat(lint-requirements): make resolving requirements optional
2 parents 16d615f + 44bc4b1 commit b294a4a

File tree

2 files changed

+54
-29
lines changed

2 files changed

+54
-29
lines changed

e2e/test_lint_requirements.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pass=true
1010

1111
# Test to demonstrate that command works as expected when input files are valid
1212

13-
if ! fromager lint-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/requirements.txt"; then
13+
if ! fromager lint-requirements --resolve-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/requirements.txt"; then
1414
echo "the input files should have been recognized as correctly formatted" 1>&2
1515
pass=false
1616
fi;
@@ -24,21 +24,21 @@ fi;
2424

2525
# Test to demonstrate that command reports error for invalid / bad requirements
2626

27-
if fromager lint-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/invalid-requirements.txt"; then
27+
if fromager lint-requirements --resolve-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/invalid-requirements.txt"; then
2828
echo "invalid input files should have been recognized by the command" 1>&2
2929
pass=false
3030
fi;
3131

3232
# Test to demonstrate that command reports error for invalid / bad constraints
3333

34-
if fromager lint-requirements "$SCRIPTDIR/validate_inputs/invalid-constraints.txt" "$SCRIPTDIR/validate_inputs/requirements.txt"; then
34+
if fromager lint-requirements --resolve-requirements "$SCRIPTDIR/validate_inputs/invalid-constraints.txt" "$SCRIPTDIR/validate_inputs/requirements.txt"; then
3535
echo "invalid input files should have been recognized by the command" 1>&2
3636
pass=false
3737
fi;
3838

3939
# Test to demonstrate that command reports error for duplicate entries in files
4040

41-
if fromager lint-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/duplicate-requirements.txt"; then
41+
if fromager lint-requirements --resolve-requirements "$SCRIPTDIR/validate_inputs/constraints.txt" "$SCRIPTDIR/validate_inputs/duplicate-requirements.txt"; then
4242
echo "duplicate entries in files should have been recognized by the command" 1>&2
4343
pass=false
4444
fi;

src/fromager/commands/lint_requirements.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,17 @@
1919
required=True,
2020
type=click.Path(exists=False, path_type=pathlib.Path),
2121
)
22+
@click.option(
23+
"--resolve-requirements/--no-resolve-requirements",
24+
default=False,
25+
help="Resolve requirement and fail if a package or version cannot be resolved",
26+
show_default=True,
27+
)
2228
@click.pass_obj
2329
def lint_requirements(
24-
wkctx: context.WorkContext, input_files_path: list[pathlib.Path]
30+
wkctx: context.WorkContext,
31+
resolve_requirements: bool,
32+
input_files_path: list[pathlib.Path],
2533
) -> None:
2634
"""
2735
Command to lint the constraints.txt and requirements.txt files
@@ -36,7 +44,7 @@ def lint_requirements(
3644
logger.error("no constraints.txt or requirements.txt found in given paths")
3745
sys.exit(1)
3846

39-
flag = True
47+
failures: list[str] = []
4048

4149
# Create bootstrapper for requirement resolution
4250
bt = bootstrapper.Bootstrapper(
@@ -48,6 +56,7 @@ def lint_requirements(
4856
)
4957

5058
for path in input_files_path:
59+
is_constraints: bool = path.name.endswith("constraints.txt")
5160
parsed_lines = requirements_file.parse_requirements_file(path)
5261
unique_entries: dict[str, Requirement] = {}
5362
for line in parsed_lines:
@@ -58,31 +67,47 @@ def lint_requirements(
5867
f"Duplicate entry, first found: {unique_entries[requirement.name]}"
5968
)
6069
unique_entries[requirement.name] = requirement
61-
if requirement.extras and path.name.endswith("constraints.txt"):
62-
raise InvalidRequirement(
63-
"Constraints files cannot contain extra dependencies"
64-
)
65-
66-
# Resolve the requirement to ensure it can be found
67-
# Skip resolution for constraints files as they should only specify versions
68-
if not path.name.endswith("constraints.txt"):
69-
token = requirement_ctxvar.set(requirement)
70-
try:
71-
_, version = bt.resolve_version(
72-
req=requirement,
73-
req_type=RequirementType.TOP_LEVEL,
70+
if is_constraints:
71+
if requirement.extras:
72+
raise InvalidRequirement(
73+
f"{requirement.name}: Constraints files cannot contain extra dependencies"
7474
)
75-
logger.info(f"{requirement} resolves to {version}")
76-
except Exception as resolve_err:
77-
logger.error(
78-
f"{path}: {line}: Failed to resolve requirement: {resolve_err}"
75+
if not requirement.specifier:
76+
raise InvalidRequirement(
77+
f"{requirement.name}: Constraints must have a version specifier"
7978
)
80-
flag = False
81-
finally:
82-
requirement_ctxvar.reset(token)
8379
except InvalidRequirement as err:
84-
logger.error(f"{path}: {line}: {err}")
85-
flag = False
80+
msg = f"{path}: {line}: {err}"
81+
logger.error(msg)
82+
failures.append(msg)
83+
84+
# Resolve the requirement to ensure it can be found
85+
# Skip resolution for constraints files as they should only specify versions
86+
if resolve_requirements and not is_constraints:
87+
token = requirement_ctxvar.set(requirement)
88+
try:
89+
_, version = bt.resolve_version(
90+
req=requirement,
91+
req_type=RequirementType.TOP_LEVEL,
92+
)
93+
logger.info(f"{requirement} resolves to {version}")
94+
except Exception as err:
95+
logger.error(
96+
f"{path}: {line}: Failed to resolve requirement: {err}"
97+
)
98+
failures.append(f"{path}: {line}: {err}")
99+
finally:
100+
requirement_ctxvar.reset(token)
86101

87-
if not flag:
102+
if failures:
103+
click.echo("Validation error:", err=True)
104+
for failure in failures:
105+
click.echo(f" - {failure}", err=True)
106+
click.echo(
107+
f"ERROR: {len(failures)} failure(s) while validating {len(input_files_path)} file(s).",
108+
err=True,
109+
)
88110
sys.exit(1)
111+
else:
112+
click.echo(f"Resolve requirements: {resolve_requirements}")
113+
click.echo(f"Successfully validated {len(input_files_path)} file(s).")

0 commit comments

Comments
 (0)