Skip to content

Commit 721ca94

Browse files
committed
Changes to integrate new parser into packaging + test adjustments
1 parent ab0db81 commit 721ca94

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

packaging/markers.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import sys
99
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
1010

11+
from ._parser import parse_quoted_marker
12+
from ._tokenizer import ParseException, Tokenizer
1113
from .specifiers import InvalidSpecifier, Specifier
1214

1315
__all__ = [
@@ -199,11 +201,11 @@ def default_environment() -> Dict[str, str]:
199201
class Marker:
200202
def __init__(self, marker: str) -> None:
201203
try:
202-
self._markers = _coerce_parse_result(MARKER.parseString(marker))
204+
self._markers = parse_quoted_marker(Tokenizer(marker))
203205
except ParseException as e:
204206
raise InvalidMarker(
205207
f"Invalid marker: {marker!r}, parse error at "
206-
f"{marker[e.loc : e.loc + 8]!r}"
208+
f"{marker[e.position : e.position + 8]!r}"
207209
)
208210

209211
def __str__(self) -> str:
@@ -224,5 +226,4 @@ def evaluate(self, environment: Optional[Dict[str, str]] = None) -> bool:
224226
current_environment = default_environment()
225227
if environment is not None:
226228
current_environment.update(environment)
227-
228229
return _evaluate_markers(self._markers, current_environment)

packaging/requirements.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
33
# for complete details.
44

5-
import re
6-
import string
75
import urllib.parse
6+
from collections import namedtuple
87
from typing import List, Optional as TOptional, Set
98

10-
from .markers import Marker
11-
from .specifiers import LegacySpecifier, Specifier, SpecifierSet
9+
from ._parser import parse_named_requirement
10+
from ._tokenizer import ParseException
11+
from .markers import InvalidMarker, Marker
12+
from .specifiers import SpecifierSet
1213

1314

1415
class InvalidRequirement(ValueError):
@@ -31,12 +32,13 @@ class Requirement:
3132
# TODO: Can we normalize the name and extra name?
3233

3334
def __init__(self, requirement_string: str) -> None:
35+
_RequirementTuple = namedtuple(
36+
"_RequirementTuple", ["name", "url", "extras", "specifier", "marker"]
37+
)
3438
try:
35-
req = REQUIREMENT.parseString(requirement_string)
39+
req = _RequirementTuple(*parse_named_requirement(requirement_string))
3640
except ParseException as e:
37-
raise InvalidRequirement(
38-
f'Parse error at "{ requirement_string[e.loc : e.loc + 8]!r}": {e.msg}'
39-
)
41+
raise InvalidRequirement(str(e))
4042

4143
self.name: str = req.name
4244
if req.url:
@@ -51,9 +53,12 @@ def __init__(self, requirement_string: str) -> None:
5153
self.url: TOptional[str] = req.url
5254
else:
5355
self.url = None
54-
self.extras: Set[str] = set(req.extras.asList() if req.extras else [])
56+
self.extras: Set[str] = set(req.extras if req.extras else [])
5557
self.specifier: SpecifierSet = SpecifierSet(req.specifier)
56-
self.marker: TOptional[Marker] = req.marker if req.marker else None
58+
try:
59+
self.marker: TOptional[Marker] = Marker(req.marker) if req.marker else None
60+
except InvalidMarker as e:
61+
raise InvalidRequirement(str(e))
5762

5863
def __str__(self) -> str:
5964
parts: List[str] = [self.name]

tests/test_markers.py

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ def test_parses_valid(self, marker_string):
161161
"python_version",
162162
"(python_version)",
163163
"python_version >= 1.0 and (python_version)",
164+
'(python_version == "2.7" and os_name == "linux"',
164165
],
165166
)
166167
def test_parses_invalid(self, marker_string):

tests/test_requirements.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pytest
66

77
from packaging.markers import Marker
8-
from packaging.requirements import URL, URL_AND_MARKER, InvalidRequirement, Requirement
8+
from packaging.requirements import InvalidRequirement, Requirement
99
from packaging.specifiers import SpecifierSet
1010

1111

@@ -59,10 +59,20 @@ def test_name_with_version(self):
5959
req = Requirement("name>=3")
6060
self._assert_requirement(req, "name", specifier=">=3")
6161

62+
def test_name_with_missing_version(self):
63+
with pytest.raises(InvalidRequirement) as e:
64+
Requirement("name>=")
65+
assert "Missing version" in str(e)
66+
6267
def test_version_with_parens_and_whitespace(self):
6368
req = Requirement("name (==4)")
6469
self._assert_requirement(req, "name", specifier="==4")
6570

71+
def test_version_with_missing_closing_paren(self):
72+
with pytest.raises(InvalidRequirement) as e:
73+
Requirement("name(==4")
74+
assert "Closing right parenthesis is missing" in str(e)
75+
6676
def test_name_with_multiple_versions(self):
6777
req = Requirement("name>=3,<2")
6878
self._assert_requirement(req, "name", specifier="<2,>=3")
@@ -79,21 +89,27 @@ def test_empty_extras(self):
7989
req = Requirement("foo[]")
8090
self._assert_requirement(req, "foo")
8191

92+
def test_unclosed_extras(self):
93+
with pytest.raises(InvalidRequirement) as e:
94+
Requirement("foo[")
95+
assert "Closing square bracket is missing" in str(e)
96+
8297
def test_url(self):
83-
url_section = "@ http://example.com"
84-
parsed = URL.parseString(url_section)
85-
assert parsed.url == "http://example.com"
98+
url_section = "test @ http://example.com"
99+
req = Requirement(url_section)
100+
self._assert_requirement(req, "test", "http://example.com", extras=[])
86101

87102
def test_url_and_marker(self):
88-
instring = "@ http://example.com ; os_name=='a'"
89-
parsed = URL_AND_MARKER.parseString(instring)
90-
assert parsed.url == "http://example.com"
91-
assert str(parsed.marker) == 'os_name == "a"'
103+
instring = "test @ http://example.com ; os_name=='a'"
104+
req = Requirement(instring)
105+
self._assert_requirement(
106+
req, "test", "http://example.com", extras=[], marker='os_name == "a"'
107+
)
92108

93109
def test_invalid_url(self):
94110
with pytest.raises(InvalidRequirement) as e:
95111
Requirement("name @ gopher:/foo/com")
96-
assert "Invalid URL: " in str(e.value)
112+
assert "Invalid URL: " in str(e)
97113
assert "gopher:/foo/com" in str(e.value)
98114

99115
def test_file_url(self):

0 commit comments

Comments
 (0)