Skip to content

Commit 2743ee0

Browse files
committed
Prepare for CTS schema changes and fix normalized slice indexes
1 parent 17ac4d5 commit 2743ee0

File tree

5 files changed

+22
-14
lines changed

5 files changed

+22
-14
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ ENV/
8383

8484
# Dev utils
8585
dev.py
86+
_dev.py
8687
profile_.py
8788
tests/test_dev.py
8889

jsonpath_rfc9535/node.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ def values(self) -> List[object]:
6767
"""Return the values from this node list."""
6868
return [node.value for node in self]
6969

70+
def paths(self) -> List[str]:
71+
"""Return normalized paths from this node list."""
72+
return [node.path() for node in self]
73+
7074
def items(self) -> List[Tuple[str, object]]:
7175
"""Return a list of (path, value) pairs, one for each node in the list."""
7276
return [(node.path(), node.value) for node in self]

jsonpath_rfc9535/selectors.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,19 +166,13 @@ def _check_range(self, *indices: Optional[int]) -> None:
166166
):
167167
raise JSONPathIndexError("index out of range", token=self.token)
168168

169-
def _normalized_index(self, obj: Sequence[object], index: int) -> int:
170-
if index < 0 and len(obj) >= abs(index):
171-
return len(obj) + index
172-
return index
173-
174169
def resolve(self, node: JSONPathNode) -> Iterable[JSONPathNode]:
175170
"""Select a range of values from an array/list."""
176171
if isinstance(node.value, list) and self.slice.step != 0:
177-
idx = self.slice.start or 0
178-
step = self.slice.step or 1
179-
for element in node.value[self.slice]:
180-
yield node.new_child(element, self._normalized_index(node.value, idx))
181-
idx += step
172+
for idx, element in zip( # noqa: B905
173+
range(*self.slice.indices(len(node.value))), node.value[self.slice]
174+
):
175+
yield node.new_child(element, idx)
182176

183177

184178
class WildcardSelector(JSONPathSelector):

jsonpath_rfc9535/serialize.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@
55

66
def canonical_string(value: str) -> str:
77
"""Return _value_ as a canonically formatted string literal."""
8-
single_quoted = json.dumps(value)[1:-1].replace('\\"', '"').replace("'", "\\'")
8+
single_quoted = (
9+
json.dumps(value, ensure_ascii=False)[1:-1]
10+
.replace('\\"', '"')
11+
.replace("'", "\\'")
12+
)
913
return f"'{single_quoted}'"

tests/test_compliance.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ class Case:
2525
selector: str
2626
document: JSONValue = None
2727
result: Any = None
28+
result_paths: Optional[List[Any]] = None
2829
results: Optional[List[Any]] = None
30+
results_paths: Optional[List[Any]] = None
2931
invalid_selector: Optional[bool] = None
3032
tags: List[str] = field(default_factory=list)
3133

@@ -53,12 +55,15 @@ def test_compliance(case: Case) -> None:
5355
pytest.skip(reason=SKIP[case.name]) # no cov
5456

5557
assert case.document is not None
56-
rv = jsonpath.JSONPathNodeList(jsonpath.find(case.selector, case.document)).values()
58+
nodes = jsonpath.JSONPathNodeList(jsonpath.find(case.selector, case.document))
5759

5860
if case.results is not None:
59-
assert rv in case.results
61+
assert isinstance(case.results_paths, list)
62+
assert nodes.values() in case.results
63+
assert nodes.paths() in case.results_paths
6064
else:
61-
assert rv == case.result
65+
assert nodes.values() == case.result
66+
assert nodes.paths() == case.result_paths
6267

6368

6469
@pytest.mark.parametrize("case", invalid_cases(), ids=operator.attrgetter("name"))

0 commit comments

Comments
 (0)