python-jsonpath 1.3.1__py3-none-any.whl → 1.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
jsonpath/__about__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2023-present James Prior <jamesgr.prior@gmail.com>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "1.3.1"
4
+ __version__ = "1.3.2"
jsonpath/__init__.py CHANGED
@@ -10,7 +10,6 @@ from .exceptions import JSONPathIndexError
10
10
  from .exceptions import JSONPathNameError
11
11
  from .exceptions import JSONPathSyntaxError
12
12
  from .exceptions import JSONPathTypeError
13
- from .exceptions import JSONPointerEncodeError
14
13
  from .exceptions import JSONPointerError
15
14
  from .exceptions import JSONPointerIndexError
16
15
  from .exceptions import JSONPointerKeyError
@@ -52,7 +51,6 @@ __all__ = (
52
51
  "JSONPathSyntaxError",
53
52
  "JSONPathTypeError",
54
53
  "JSONPointer",
55
- "JSONPointerEncodeError",
56
54
  "JSONPointerError",
57
55
  "JSONPointerIndexError",
58
56
  "JSONPointerKeyError",
jsonpath/env.py CHANGED
@@ -99,7 +99,7 @@ class JSONPathEnvironment:
99
99
  intersection_token (str): The pattern used as the intersection operator.
100
100
  Defaults to `"&"`.
101
101
  key_token (str): The pattern used to identify the current key or index when
102
- filtering a, mapping or sequence. Defaults to `"#"`.
102
+ filtering a mapping or sequence. Defaults to `"#"`.
103
103
  keys_selector_token (str): The pattern used as the "keys" selector. Defaults to
104
104
  `"~"`.
105
105
  lexer_class: The lexer to use when tokenizing path strings.
jsonpath/exceptions.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """JSONPath exceptions."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TYPE_CHECKING
@@ -80,10 +81,6 @@ class JSONPointerError(Exception):
80
81
  """Base class for all JSON Pointer errors."""
81
82
 
82
83
 
83
- class JSONPointerEncodeError(JSONPointerError):
84
- """An exception raised when a JSONPathMatch can't be encoded to a JSON Pointer."""
85
-
86
-
87
84
  class JSONPointerResolutionError(JSONPointerError):
88
85
  """Base exception for those that can be raised during pointer resolution."""
89
86
 
@@ -145,7 +142,7 @@ class JSONPatchTestFailure(JSONPatchError): # noqa: N818
145
142
  def _truncate_message(value: str, num: int, end: str = "...") -> str:
146
143
  if len(value) < num:
147
144
  return value
148
- return f"{value[:num-len(end)]}{end}"
145
+ return f"{value[: num - len(end)]}{end}"
149
146
 
150
147
 
151
148
  def _truncate_words(val: str, num: int, end: str = "...") -> str:
jsonpath/filter.py CHANGED
@@ -544,7 +544,12 @@ class SelfPath(Path):
544
544
  return context.current
545
545
  return NodeList()
546
546
 
547
- return NodeList(self.path.finditer(context.current))
547
+ return NodeList(
548
+ self.path.finditer(
549
+ context.current,
550
+ filter_context=context.extra_context,
551
+ )
552
+ )
548
553
 
549
554
  async def evaluate_async(self, context: FilterContext) -> object:
550
555
  if isinstance(context.current, str): # TODO: refactor
@@ -557,7 +562,13 @@ class SelfPath(Path):
557
562
  return NodeList()
558
563
 
559
564
  return NodeList(
560
- [match async for match in await self.path.finditer_async(context.current)]
565
+ [
566
+ match
567
+ async for match in await self.path.finditer_async(
568
+ context.current,
569
+ filter_context=context.extra_context,
570
+ )
571
+ ]
561
572
  )
562
573
 
563
574
 
@@ -576,11 +587,22 @@ class RootPath(Path):
576
587
  return str(self.path)
577
588
 
578
589
  def evaluate(self, context: FilterContext) -> object:
579
- return NodeList(self.path.finditer(context.root))
590
+ return NodeList(
591
+ self.path.finditer(
592
+ context.root,
593
+ filter_context=context.extra_context,
594
+ )
595
+ )
580
596
 
581
597
  async def evaluate_async(self, context: FilterContext) -> object:
582
598
  return NodeList(
583
- [match async for match in await self.path.finditer_async(context.root)]
599
+ [
600
+ match
601
+ async for match in await self.path.finditer_async(
602
+ context.root,
603
+ filter_context=context.extra_context,
604
+ )
605
+ ]
584
606
  )
585
607
 
586
608
 
@@ -600,13 +622,21 @@ class FilterContextPath(Path):
600
622
  return "_" + path_repr[1:]
601
623
 
602
624
  def evaluate(self, context: FilterContext) -> object:
603
- return NodeList(self.path.finditer(context.extra_context))
625
+ return NodeList(
626
+ self.path.finditer(
627
+ context.extra_context,
628
+ filter_context=context.extra_context,
629
+ )
630
+ )
604
631
 
605
632
  async def evaluate_async(self, context: FilterContext) -> object:
606
633
  return NodeList(
607
634
  [
608
635
  match
609
- async for match in await self.path.finditer_async(context.extra_context)
636
+ async for match in await self.path.finditer_async(
637
+ context.extra_context,
638
+ filter_context=context.extra_context,
639
+ )
610
640
  ]
611
641
  )
612
642
 
jsonpath/pointer.py CHANGED
@@ -32,7 +32,7 @@ if TYPE_CHECKING:
32
32
 
33
33
  class _Undefined:
34
34
  def __str__(self) -> str:
35
- return "<jsonpath.pointer.UNDEFINED>"
35
+ return "<jsonpath.pointer.UNDEFINED>" # pragma: no cover
36
36
 
37
37
 
38
38
  UNDEFINED = _Undefined()
@@ -115,59 +115,83 @@ class JSONPointer:
115
115
  try:
116
116
  index = int(s)
117
117
  if index < self.min_int_index or index > self.max_int_index:
118
- raise JSONPointerIndexError("index out of range")
118
+ raise JSONPointerError("index out of range")
119
119
  return index
120
120
  except ValueError:
121
121
  return s
122
122
 
123
- def _getitem(self, obj: Any, key: Any) -> Any: # noqa: PLR0912
123
+ def _getitem(self, obj: Any, key: Any) -> Any:
124
124
  try:
125
+ # Handle the most common cases. A mapping with a string key, or a sequence
126
+ # with an integer index.
127
+ #
128
+ # Note that `obj` does not have to be a Mapping or Sequence here. Any object
129
+ # implementing `__getitem__` will do.
125
130
  return getitem(obj, key)
126
131
  except KeyError as err:
127
- # Try a string repr of the index-like item as a mapping key.
128
- if isinstance(key, int):
129
- try:
130
- return getitem(obj, str(key))
131
- except KeyError:
132
- raise JSONPointerKeyError(key) from err
133
- # Handle non-standard keys/property selector/pointer.
134
- if (
135
- isinstance(key, str)
136
- and isinstance(obj, Mapping)
137
- and key.startswith((self.keys_selector, "#"))
138
- and key[1:] in obj
139
- ):
140
- return key[1:]
141
- # Handle non-standard index/property pointer (`#`)
142
- raise JSONPointerKeyError(key) from err
132
+ return self._handle_key_error(obj, key, err)
143
133
  except TypeError as err:
144
- if isinstance(obj, Sequence) and not isinstance(obj, str):
145
- if key == "-":
146
- # "-" is a valid index when appending to a JSON array
147
- # with JSON Patch, but not when resolving a JSON Pointer.
148
- raise JSONPointerIndexError("index out of range") from None
149
- # Handle non-standard index pointer.
150
- if isinstance(key, str) and key.startswith("#"):
151
- _index = int(key[1:])
152
- if _index >= len(obj):
153
- raise JSONPointerIndexError(
154
- f"index out of range: {_index}"
155
- ) from err
156
- return _index
157
- # Try int index. Reject non-zero ints that start with a zero.
158
- if isinstance(key, str):
159
- index = self._index(key)
160
- if isinstance(index, int):
161
- try:
162
- return getitem(obj, int(key))
163
- except IndexError as index_err:
164
- raise JSONPointerIndexError(
165
- f"index out of range: {key}"
166
- ) from index_err
167
- raise JSONPointerTypeError(f"{key}: {err}") from err
134
+ return self._handle_type_error(obj, key, err)
168
135
  except IndexError as err:
169
136
  raise JSONPointerIndexError(f"index out of range: {key}") from err
170
137
 
138
+ def _handle_key_error(self, obj: Any, key: Any, err: Exception) -> object:
139
+ if isinstance(key, int):
140
+ # Try a string repr of the index-like item as a mapping key.
141
+ return self._getitem(obj, str(key))
142
+
143
+ # Handle non-standard key/property selector/pointer.
144
+ #
145
+ # For the benefit of `RelativeJSONPointer.to()` and `JSONPathMatch.pointer()`,
146
+ # treat keys starting with a `#` or `~` as a "key pointer". If `key[1:]` is a
147
+ # key in `obj`, return the key.
148
+ #
149
+ # Note that if a key with a leading `#`/`~` exists in `obj`, it will have been
150
+ # handled by `_getitem`.
151
+ if (
152
+ isinstance(key, str)
153
+ and isinstance(obj, Mapping)
154
+ and key.startswith((self.keys_selector, "#"))
155
+ and key[1:] in obj
156
+ ):
157
+ return key[1:]
158
+
159
+ raise JSONPointerKeyError(key) from err
160
+
161
+ def _handle_type_error(self, obj: Any, key: Any, err: Exception) -> object:
162
+ if (
163
+ isinstance(obj, str)
164
+ or not isinstance(obj, Sequence)
165
+ or not isinstance(key, str)
166
+ ):
167
+ raise JSONPointerTypeError(f"{key}: {err}") from err
168
+
169
+ # `obj` is array-like
170
+ # `key` is a string
171
+
172
+ if key == "-":
173
+ # "-" is a valid index when appending to a JSON array with JSON Patch, but
174
+ # not when resolving a JSON Pointer.
175
+ raise JSONPointerIndexError("index out of range") from None
176
+
177
+ # Handle non-standard index pointer.
178
+ #
179
+ # For the benefit of `RelativeJSONPointer.to()`, treat keys starting with a `#`
180
+ # and followed by a valid index as an "index pointer". If `int(key[1:])` is
181
+ # less than `len(obj)`, return the index.
182
+ if re.match(r"#[1-9]\d*", key):
183
+ _index = int(key[1:])
184
+ if _index >= len(obj):
185
+ raise JSONPointerIndexError(f"index out of range: {_index}") from err
186
+ return _index
187
+
188
+ # Try int index. Reject non-zero ints that start with a zero.
189
+ index = self._index(key)
190
+ if isinstance(index, int):
191
+ return self._getitem(obj, index)
192
+
193
+ raise JSONPointerTypeError(f"{key}: {err}") from err
194
+
171
195
  def resolve(
172
196
  self,
173
197
  data: Union[str, IOBase, Sequence[object], Mapping[str, object]],
@@ -263,7 +287,7 @@ class JSONPointer:
263
287
  pointer = cls._encode(match.parts)
264
288
  else:
265
289
  # This should not happen, unless the JSONPathMatch has been tampered with.
266
- pointer = ""
290
+ pointer = "" # pragma: no cover
267
291
 
268
292
  return cls(
269
293
  pointer,
@@ -328,10 +352,10 @@ class JSONPointer:
328
352
  return isinstance(other, JSONPointer) and self.parts == other.parts
329
353
 
330
354
  def __hash__(self) -> int:
331
- return hash(self.parts)
355
+ return hash(self.parts) # pragma: no cover
332
356
 
333
357
  def __repr__(self) -> str:
334
- return f"JSONPointer({self._s!r})"
358
+ return f"JSONPointer({self._s!r})" # pragma: no cover
335
359
 
336
360
  def exists(
337
361
  self, data: Union[str, IOBase, Sequence[object], Mapping[str, object]]
@@ -486,7 +510,7 @@ class RelativeJSONPointer:
486
510
  return isinstance(__value, RelativeJSONPointer) and str(self) == str(__value)
487
511
 
488
512
  def __hash__(self) -> int:
489
- return hash((self.origin, self.index, self.pointer))
513
+ return hash((self.origin, self.index, self.pointer)) # pragma: no cover
490
514
 
491
515
  def _parse(
492
516
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jsonpath
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: JSONPath, JSON Pointer and JSON Patch for Python.
5
5
  Project-URL: Documentation, https://jg-rp.github.io/python-jsonpath/
6
6
  Project-URL: Issues, https://github.com/jg-rp/python-jsonpath/issues
@@ -1,18 +1,18 @@
1
- jsonpath/__about__.py,sha256=gvEMxyEUsNjYzzau44eiB6YzOhHDm8YRiKAjgKjAExk,132
2
- jsonpath/__init__.py,sha256=RTvhFGRb7yLLPUe80a6qD2WAv9gXRe5J69kx0-K6HXc,2412
1
+ jsonpath/__about__.py,sha256=lKzAT7eRQ0XCM36oMem3ZY_sdLarE9W-QFI1Ret5qKc,132
2
+ jsonpath/__init__.py,sha256=WlqHtXZcMy2AnAqvBQeiUcS1_I7Upif2j7SSLYZGTNg,2335
3
3
  jsonpath/__main__.py,sha256=6Y5wOE7U-MHymopXOsxofaY30tVZYPGTJO0L4vytoUw,61
4
4
  jsonpath/_data.py,sha256=JEpu5Kg0_kgxYKUilBcHVdTmPxf3-Vc0NgaW6olsqyY,577
5
5
  jsonpath/cli.py,sha256=scpWfJXl1jLQ80ZyXqMCu8JtRgZUXluC11x6OkC4oeA,10026
6
- jsonpath/env.py,sha256=EqlLT6_WE7WbChNs_xDipF7V8uGG3EnyKabJ_bstpGs,22815
7
- jsonpath/exceptions.py,sha256=5n-9vaKTu5asWllHT0IN-824ewcNCyQIyKvQ58TERVk,4351
8
- jsonpath/filter.py,sha256=hat_VU2aXXGUyb7QEYpziW2YRx1DkbJhRCFP_lEPI0M,22051
6
+ jsonpath/env.py,sha256=Q3ymsGf0ktpiVGU5OLjYCayHFCEfN-jvZCjFzFJJ3HU,22814
7
+ jsonpath/exceptions.py,sha256=ku3XNuMn4CsYhe-iZpZ8DuFPR2AEcV0SEl55X3Huhaw,4218
8
+ jsonpath/filter.py,sha256=Ay71K1PzI3_Vur5Y7pAQguV0ceo4yqBZVsuj_jD7nck,22755
9
9
  jsonpath/fluent_api.py,sha256=mfAA2t-xUGOmGVr_1h9lxo3y4FsAvaxOpvOH8jZ4DHU,9117
10
10
  jsonpath/lex.py,sha256=8yrSLd3Q3A9Y4GeacOjboUp40XsR_BkRDQ3CC3UVcP8,10296
11
11
  jsonpath/match.py,sha256=qJ8IUn8RsuC-iL6RKr2vTn0l1f7bcx1m9cnZiAEqYH0,3657
12
12
  jsonpath/parse.py,sha256=s7BuFsSgX2GuDubrFr-SDcCk2ZInGzPV04FNFcUwxPM,25214
13
13
  jsonpath/patch.py,sha256=T6CP0GDJg6drD9qWs6ueRFdQRhXj_xPGEtW5x01iJb8,25388
14
14
  jsonpath/path.py,sha256=RUeP7k_WcvP5ZnYblcRDd_-wgo9VnMKyIevTcRImYE4,16421
15
- jsonpath/pointer.py,sha256=ERoBZvw5QlA7aRaecRTYPiQRFLbwTBe41deguJVOf0k,22392
15
+ jsonpath/pointer.py,sha256=UjqqWQWL8D-chjSEQ2al_Ev5xcHaKxFFfQxPfuBSwO0,23100
16
16
  jsonpath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  jsonpath/selectors.py,sha256=oesy964W8Qd1qSSb0qtWJY63A2D0lZc0ppF-pGEYmgU,27313
18
18
  jsonpath/serialize.py,sha256=viMcWY52wkUseTNfPKillVWswHePJ2L_B3PV3bDVvmU,360
@@ -29,8 +29,8 @@ jsonpath/function_extensions/match.py,sha256=KjsH33fCFGonp2RV__FuaeIOTwLLcvgaaCi
29
29
  jsonpath/function_extensions/search.py,sha256=O11fnkHlbvf0QPrLISYfhlPXBvVPBr-U8V0dGbd614Y,710
30
30
  jsonpath/function_extensions/typeof.py,sha256=yCAj9zOqSnam1mfHCGolNHWDmsBOvU3rAhbZDYycx50,1780
31
31
  jsonpath/function_extensions/value.py,sha256=fQMbPUV87Jn1nOwAlBpTeLmLIG5ejH0XQBOM_SR-Us4,721
32
- python_jsonpath-1.3.1.dist-info/METADATA,sha256=h7wTnS0BuY1FAC3CaPugqm1U5B8k0UFi-XP-70d98Ws,6493
33
- python_jsonpath-1.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
- python_jsonpath-1.3.1.dist-info/entry_points.txt,sha256=xvbWnAebJyOMI_9ugK0xrpFRlwmEsAJD2kNHU0Dvscc,43
35
- python_jsonpath-1.3.1.dist-info/licenses/LICENSE.txt,sha256=u7PksAQGI1QYWcERHeauMseZ4XAzDKUrKW8Z4wbeU1k,1101
36
- python_jsonpath-1.3.1.dist-info/RECORD,,
32
+ python_jsonpath-1.3.2.dist-info/METADATA,sha256=_fv6UDYXR5zUSS_JPOqW8yM4pgdLxz-MhHS1b4BN_qg,6493
33
+ python_jsonpath-1.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
34
+ python_jsonpath-1.3.2.dist-info/entry_points.txt,sha256=xvbWnAebJyOMI_9ugK0xrpFRlwmEsAJD2kNHU0Dvscc,43
35
+ python_jsonpath-1.3.2.dist-info/licenses/LICENSE.txt,sha256=u7PksAQGI1QYWcERHeauMseZ4XAzDKUrKW8Z4wbeU1k,1101
36
+ python_jsonpath-1.3.2.dist-info/RECORD,,