From 7930b73d5815f475028a2600c47fb340ad72f40c Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Tue, 6 Dec 2022 00:24:11 +0000 Subject: [PATCH] Improve error message for bad version specifiers in `Requirement` This makes it easier to understand what the state of the parser is and what is expected at that point. --- packaging/_parser.py | 8 +++++++- tests/test_requirements.py | 18 +++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packaging/_parser.py b/packaging/_parser.py index 378cef88..29cb27d3 100644 --- a/packaging/_parser.py +++ b/packaging/_parser.py @@ -120,7 +120,13 @@ def _parse_requirement_details( return (url, specifier, marker) marker = _parse_requirement_marker( - tokenizer, span_start=specifier_start, after="version specifier" + tokenizer, + span_start=specifier_start, + after=( + "version specifier" + if specifier + else "name and no valid version specifier" + ), ) return (url, specifier, marker) diff --git a/tests/test_requirements.py b/tests/test_requirements.py index 09c963d0..5305fbdf 100644 --- a/tests/test_requirements.py +++ b/tests/test_requirements.py @@ -489,11 +489,27 @@ def test_error_on_missing_op_after_name(self) -> None: # THEN assert ctx.exconly() == ( "packaging.requirements.InvalidRequirement: " - "Expected end or semicolon (after version specifier)\n" + "Expected end or semicolon (after name and no valid version specifier)\n" " name 1.0\n" " ^" ) + def test_error_on_random_char_after_specifier(self) -> None: + # GIVEN + to_parse = "name >= 1.0 #" + + # WHEN + with pytest.raises(InvalidRequirement) as ctx: + Requirement(to_parse) + + # THEN + assert ctx.exconly() == ( + "packaging.requirements.InvalidRequirement: " + "Expected end or semicolon (after version specifier)\n" + " name >= 1.0 #\n" + " ~~~~~~~^" + ) + class TestRequirementBehaviour: def test_types_with_nothing(self) -> None: