Skip to content

Commit 1a55574

Browse files
authored
Report detailed information about invalid requirements (#12715)
1 parent d929bfe commit 1a55574

File tree

5 files changed

+18
-10
lines changed

5 files changed

+18
-10
lines changed

news/12713.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Report informative messages about invalid requirements.

src/pip/_internal/req/constructors.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts:
206206
if name is not None:
207207
try:
208208
req: Optional[Requirement] = Requirement(name)
209-
except InvalidRequirement:
210-
raise InstallationError(f"Invalid requirement: '{name}'")
209+
except InvalidRequirement as exc:
210+
raise InstallationError(f"Invalid requirement: {name!r}: {exc}")
211211
else:
212212
req = None
213213

@@ -360,7 +360,7 @@ def with_source(text: str) -> str:
360360
def _parse_req_string(req_as_string: str) -> Requirement:
361361
try:
362362
return get_requirement(req_as_string)
363-
except InvalidRequirement:
363+
except InvalidRequirement as exc:
364364
if os.path.sep in req_as_string:
365365
add_msg = "It looks like a path."
366366
add_msg += deduce_helpful_msg(req_as_string)
@@ -370,7 +370,7 @@ def _parse_req_string(req_as_string: str) -> Requirement:
370370
add_msg = "= is not a valid operator. Did you mean == ?"
371371
else:
372372
add_msg = ""
373-
msg = with_source(f"Invalid requirement: {req_as_string!r}")
373+
msg = with_source(f"Invalid requirement: {req_as_string!r}: {exc}")
374374
if add_msg:
375375
msg += f"\nHint: {add_msg}"
376376
raise InstallationError(msg)
@@ -429,8 +429,8 @@ def install_req_from_req_string(
429429
) -> InstallRequirement:
430430
try:
431431
req = get_requirement(req_string)
432-
except InvalidRequirement:
433-
raise InstallationError(f"Invalid requirement: '{req_string}'")
432+
except InvalidRequirement as exc:
433+
raise InstallationError(f"Invalid requirement: {req_string!r}: {exc}")
434434

435435
domains_not_allowed = [
436436
PyPI.file_storage_domain,

tests/unit/test_req.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ def test_unidentifiable_name(self) -> None:
734734
with pytest.raises(InstallationError) as e:
735735
install_req_from_line(test_name)
736736
err_msg = e.value.args[0]
737-
assert f"Invalid requirement: '{test_name}'" == err_msg
737+
assert err_msg.startswith(f"Invalid requirement: '{test_name}'")
738738

739739
def test_requirement_file(self) -> None:
740740
req_file_path = os.path.join(self.tempdir, "test.txt")

tests/unit/test_req_file.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,10 @@ def test_error_message(self, line_processor: LineProcessor) -> None:
269269
)
270270

271271
expected = (
272-
"Invalid requirement: 'my-package=1.0' "
273-
"(from line 3 of path/requirements.txt)\n"
272+
"Invalid requirement: 'my-package=1.0': "
273+
"Expected end or semicolon (after name and no valid version specifier)\n"
274+
" my-package=1.0\n"
275+
" ^ (from line 3 of path/requirements.txt)\n"
274276
"Hint: = is not a valid operator. Did you mean == ?"
275277
)
276278
assert str(exc.value) == expected

tests/unit/test_req_install.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ def test_install_req_from_string_invalid_requirement(self) -> None:
6060
with pytest.raises(InstallationError) as excinfo:
6161
install_req_from_req_string("http:/this/is/invalid")
6262

63-
assert str(excinfo.value) == ("Invalid requirement: 'http:/this/is/invalid'")
63+
assert str(excinfo.value) == (
64+
"Invalid requirement: 'http:/this/is/invalid': "
65+
"Expected end or semicolon (after name and no valid version specifier)\n"
66+
" http:/this/is/invalid\n"
67+
" ^"
68+
)
6469

6570
def test_install_req_from_string_without_comes_from(self) -> None:
6671
"""

0 commit comments

Comments
 (0)