python-jsonpath 1.2.2__py3-none-any.whl → 1.3.1__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.2.2"
4
+ __version__ = "1.3.1"
jsonpath/__init__.py CHANGED
@@ -24,6 +24,7 @@ from .fluent_api import Projection
24
24
  from .fluent_api import Query
25
25
  from .lex import Lexer
26
26
  from .match import JSONPathMatch
27
+ from .match import NodeList
27
28
  from .parse import Parser
28
29
  from .patch import JSONPatch
29
30
  from .path import CompoundJSONPath
@@ -58,6 +59,7 @@ __all__ = (
58
59
  "JSONPointerResolutionError",
59
60
  "JSONPointerTypeError",
60
61
  "Lexer",
62
+ "NodeList",
61
63
  "match",
62
64
  "Parser",
63
65
  "Projection",
jsonpath/filter.py CHANGED
@@ -3,7 +3,6 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import copy
6
- import json
7
6
  import re
8
7
  from abc import ABC
9
8
  from abc import abstractmethod
@@ -25,12 +24,13 @@ from .function_extensions import FilterFunction
25
24
  from .match import NodeList
26
25
  from .selectors import Filter as FilterSelector
27
26
  from .selectors import ListSelector
27
+ from .serialize import canonical_string
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  from .path import JSONPath
31
31
  from .selectors import FilterContext
32
32
 
33
- # ruff: noqa: D102
33
+ # ruff: noqa: D102, PLW1641
34
34
 
35
35
 
36
36
  class FilterExpression(ABC):
@@ -208,7 +208,7 @@ class StringLiteral(Literal[str]):
208
208
  __slots__ = ()
209
209
 
210
210
  def __str__(self) -> str:
211
- return json.dumps(self.value)
211
+ return canonical_string(self.value)
212
212
 
213
213
 
214
214
  class IntegerLiteral(Literal[int]):
@@ -375,6 +375,12 @@ class InfixExpression(FilterExpression):
375
375
  self.right = children[1]
376
376
 
377
377
 
378
+ PRECEDENCE_LOWEST = 1
379
+ PRECEDENCE_LOGICAL_OR = 3
380
+ PRECEDENCE_LOGICAL_AND = 4
381
+ PRECEDENCE_PREFIX = 7
382
+
383
+
378
384
  class BooleanExpression(FilterExpression):
379
385
  """An expression that always evaluates to `True` or `False`."""
380
386
 
@@ -408,13 +414,40 @@ class BooleanExpression(FilterExpression):
408
414
  )
409
415
 
410
416
  def __str__(self) -> str:
411
- return str(self.expression)
417
+ return self._canonical_string(self.expression, PRECEDENCE_LOWEST)
412
418
 
413
419
  def __eq__(self, other: object) -> bool:
414
420
  return (
415
421
  isinstance(other, BooleanExpression) and self.expression == other.expression
416
422
  )
417
423
 
424
+ def _canonical_string(
425
+ self, expression: FilterExpression, parent_precedence: int
426
+ ) -> str:
427
+ if isinstance(expression, InfixExpression):
428
+ if expression.operator == "&&":
429
+ left = self._canonical_string(expression.left, PRECEDENCE_LOGICAL_AND)
430
+ right = self._canonical_string(expression.right, PRECEDENCE_LOGICAL_AND)
431
+ expr = f"{left} && {right}"
432
+ return (
433
+ f"({expr})" if parent_precedence >= PRECEDENCE_LOGICAL_AND else expr
434
+ )
435
+
436
+ if expression.operator == "||":
437
+ left = self._canonical_string(expression.left, PRECEDENCE_LOGICAL_OR)
438
+ right = self._canonical_string(expression.right, PRECEDENCE_LOGICAL_OR)
439
+ expr = f"{left} || {right}"
440
+ return (
441
+ f"({expr})" if parent_precedence >= PRECEDENCE_LOGICAL_OR else expr
442
+ )
443
+
444
+ if isinstance(expression, PrefixExpression):
445
+ operand = self._canonical_string(expression.right, PRECEDENCE_PREFIX)
446
+ expr = f"!{operand}"
447
+ return f"({expr})" if parent_precedence > PRECEDENCE_PREFIX else expr
448
+
449
+ return str(expression)
450
+
418
451
  def evaluate(self, context: FilterContext) -> bool:
419
452
  return context.env.is_truthy(self.expression.evaluate(context))
420
453
 
@@ -1,4 +1,5 @@
1
1
  """Class-based function extension base."""
2
+
2
3
  import inspect
3
4
  from typing import TYPE_CHECKING
4
5
  from typing import Any
@@ -26,7 +27,7 @@ def validate(
26
27
  params = list(inspect.signature(func).parameters.values())
27
28
 
28
29
  # Keyword only params are not supported
29
- if len([p for p in params if p.kind in (p.KEYWORD_ONLY, p.VAR_KEYWORD)]):
30
+ if [p for p in params if p.kind in (p.KEYWORD_ONLY, p.VAR_KEYWORD)]:
30
31
  raise JSONPathTypeError(
31
32
  f"function {token.value!r} requires keyword arguments",
32
33
  token=token,
jsonpath/match.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """The JSONPath match object, as returned from `JSONPath.finditer()`."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import Any
@@ -104,6 +105,10 @@ class NodeList(List[JSONPathMatch]):
104
105
  return self[0].obj
105
106
  return [match.obj for match in self]
106
107
 
108
+ def paths(self) -> List[str]:
109
+ """Return a normalized path for each node in this node list."""
110
+ return [match.path for match in self]
111
+
107
112
  def empty(self) -> bool:
108
113
  """Return `True` if this node list is empty."""
109
114
  return not bool(self)
jsonpath/patch.py CHANGED
@@ -74,7 +74,7 @@ class OpAdd(Op):
74
74
  else:
75
75
  parent.insert(int(target), self.value)
76
76
  elif isinstance(parent, MutableMapping):
77
- parent[target] = self.value
77
+ parent[str(target)] = self.value
78
78
  else:
79
79
  raise JSONPatchError(
80
80
  f"unexpected operation on {parent.__class__.__name__!r}"
@@ -124,7 +124,7 @@ class OpAddAp(OpAdd):
124
124
  """A non-standard add operation that appends to arrays/lists .
125
125
 
126
126
  This is like _OpAdd_, but assumes an index of "-" if the path can not
127
- be resolved.
127
+ be resolved rather than raising a JSONPatchError.
128
128
 
129
129
  **New in version 1.2.0**
130
130
  """
@@ -183,7 +183,7 @@ class OpRemove(Op):
183
183
  elif isinstance(parent, MutableMapping):
184
184
  if obj is UNDEFINED:
185
185
  raise JSONPatchError("can't remove nonexistent property")
186
- del parent[self.path.parts[-1]]
186
+ del parent[str(self.path.parts[-1])]
187
187
  else:
188
188
  raise JSONPatchError(
189
189
  f"unexpected operation on {parent.__class__.__name__!r}"
@@ -221,7 +221,7 @@ class OpReplace(Op):
221
221
  elif isinstance(parent, MutableMapping):
222
222
  if obj is UNDEFINED:
223
223
  raise JSONPatchError("can't replace nonexistent property")
224
- parent[self.path.parts[-1]] = self.value
224
+ parent[str(self.path.parts[-1])] = self.value
225
225
  else:
226
226
  raise JSONPatchError(
227
227
  f"unexpected operation on {parent.__class__.__name__!r}"
@@ -259,7 +259,7 @@ class OpMove(Op):
259
259
  if isinstance(source_parent, MutableSequence):
260
260
  del source_parent[int(self.source.parts[-1])]
261
261
  if isinstance(source_parent, MutableMapping):
262
- del source_parent[self.source.parts[-1]]
262
+ del source_parent[str(self.source.parts[-1])]
263
263
 
264
264
  dest_parent, _ = self.dest.resolve_parent(data)
265
265
 
@@ -270,7 +270,7 @@ class OpMove(Op):
270
270
  if isinstance(dest_parent, MutableSequence):
271
271
  dest_parent.insert(int(self.dest.parts[-1]), source_obj)
272
272
  elif isinstance(dest_parent, MutableMapping):
273
- dest_parent[self.dest.parts[-1]] = source_obj
273
+ dest_parent[str(self.dest.parts[-1])] = source_obj
274
274
  else:
275
275
  raise JSONPatchError(
276
276
  f"unexpected operation on {dest_parent.__class__.__name__!r}"
@@ -312,7 +312,7 @@ class OpCopy(Op):
312
312
  if isinstance(dest_parent, MutableSequence):
313
313
  dest_parent.insert(int(self.dest.parts[-1]), copy.deepcopy(source_obj))
314
314
  elif isinstance(dest_parent, MutableMapping):
315
- dest_parent[self.dest.parts[-1]] = copy.deepcopy(source_obj)
315
+ dest_parent[str(self.dest.parts[-1])] = copy.deepcopy(source_obj)
316
316
  else:
317
317
  raise JSONPatchError(
318
318
  f"unexpected operation on {dest_parent.__class__.__name__!r}"
@@ -419,7 +419,7 @@ class JSONPatch:
419
419
  value=self._op_value(operation, "value", "addne", i),
420
420
  )
421
421
  elif op == "addap":
422
- self.addne(
422
+ self.addap(
423
423
  path=self._op_pointer(operation, "path", "addap", i),
424
424
  value=self._op_value(operation, "value", "addap", i),
425
425
  )
jsonpath/pointer.py CHANGED
@@ -485,6 +485,9 @@ class RelativeJSONPointer:
485
485
  def __eq__(self, __value: object) -> bool:
486
486
  return isinstance(__value, RelativeJSONPointer) and str(self) == str(__value)
487
487
 
488
+ def __hash__(self) -> int:
489
+ return hash((self.origin, self.index, self.pointer))
490
+
488
491
  def _parse(
489
492
  self,
490
493
  rel: str,
jsonpath/selectors.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """JSONPath segments and selectors, as returned from `Parser.parse`."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from abc import ABC
@@ -17,6 +18,7 @@ from typing import Union
17
18
 
18
19
  from .exceptions import JSONPathIndexError
19
20
  from .exceptions import JSONPathTypeError
21
+ from .serialize import canonical_string
20
22
 
21
23
  if TYPE_CHECKING:
22
24
  from .env import JSONPathEnvironment
@@ -75,7 +77,11 @@ class PropertySelector(JSONPathSelector):
75
77
  self.shorthand = shorthand
76
78
 
77
79
  def __str__(self) -> str:
78
- return f"['{self.name}']" if self.shorthand else f"'{self.name}'"
80
+ return (
81
+ f"[{canonical_string(self.name)}]"
82
+ if self.shorthand
83
+ else f"{canonical_string(self.name)}"
84
+ )
79
85
 
80
86
  def __eq__(self, __value: object) -> bool:
81
87
  return (
@@ -98,7 +104,7 @@ class PropertySelector(JSONPathSelector):
98
104
  obj=self.env.getitem(match.obj, self.name),
99
105
  parent=match,
100
106
  parts=match.parts + (self.name,),
101
- path=match.path + f"['{self.name}']",
107
+ path=match.path + f"[{canonical_string(self.name)}]",
102
108
  root=match.root,
103
109
  )
104
110
  match.add_child(_match)
@@ -117,7 +123,7 @@ class PropertySelector(JSONPathSelector):
117
123
  obj=await self.env.getitem_async(match.obj, self.name),
118
124
  parent=match,
119
125
  parts=match.parts + (self.name,),
120
- path=match.path + f"['{self.name}']",
126
+ path=match.path + f"[{canonical_string(self.name)}]",
121
127
  root=match.root,
122
128
  )
123
129
  match.add_child(_match)
@@ -321,20 +327,15 @@ class SliceSelector(JSONPathSelector):
321
327
  ):
322
328
  raise JSONPathIndexError("index out of range", token=self.token)
323
329
 
324
- def _normalized_index(self, obj: Sequence[object], index: int) -> int:
325
- if index < 0 and len(obj) >= abs(index):
326
- return len(obj) + index
327
- return index
328
-
329
330
  def resolve(self, matches: Iterable[JSONPathMatch]) -> Iterable[JSONPathMatch]:
330
331
  for match in matches:
331
332
  if not isinstance(match.obj, Sequence) or self.slice.step == 0:
332
333
  continue
333
334
 
334
- idx = self.slice.start or 0
335
- step = self.slice.step or 1
336
- for obj in self.env.getitem(match.obj, self.slice):
337
- norm_index = self._normalized_index(match.obj, idx)
335
+ for norm_index, obj in zip( # noqa: B905
336
+ range(*self.slice.indices(len(match.obj))),
337
+ self.env.getitem(match.obj, self.slice),
338
+ ):
338
339
  _match = self.env.match_class(
339
340
  filter_context=match.filter_context(),
340
341
  obj=obj,
@@ -345,7 +346,6 @@ class SliceSelector(JSONPathSelector):
345
346
  )
346
347
  match.add_child(_match)
347
348
  yield _match
348
- idx += step
349
349
 
350
350
  async def resolve_async(
351
351
  self, matches: AsyncIterable[JSONPathMatch]
@@ -354,10 +354,10 @@ class SliceSelector(JSONPathSelector):
354
354
  if not isinstance(match.obj, Sequence) or self.slice.step == 0:
355
355
  continue
356
356
 
357
- idx = self.slice.start or 0
358
- step = self.slice.step or 1
359
- for obj in await self.env.getitem_async(match.obj, self.slice):
360
- norm_index = self._normalized_index(match.obj, idx)
357
+ for norm_index, obj in zip( # noqa: B905
358
+ range(*self.slice.indices(len(match.obj))),
359
+ await self.env.getitem_async(match.obj, self.slice),
360
+ ):
361
361
  _match = self.env.match_class(
362
362
  filter_context=match.filter_context(),
363
363
  obj=obj,
@@ -368,7 +368,6 @@ class SliceSelector(JSONPathSelector):
368
368
  )
369
369
  match.add_child(_match)
370
370
  yield _match
371
- idx += step
372
371
 
373
372
 
374
373
  class WildSelector(JSONPathSelector):
@@ -402,7 +401,7 @@ class WildSelector(JSONPathSelector):
402
401
  obj=val,
403
402
  parent=match,
404
403
  parts=match.parts + (key,),
405
- path=match.path + f"['{key}']",
404
+ path=match.path + f"[{canonical_string(key)}]",
406
405
  root=match.root,
407
406
  )
408
407
  match.add_child(_match)
@@ -431,7 +430,7 @@ class WildSelector(JSONPathSelector):
431
430
  obj=val,
432
431
  parent=match,
433
432
  parts=match.parts + (key,),
434
- path=match.path + f"['{key}']",
433
+ path=match.path + f"[{canonical_string(key)}]",
435
434
  root=match.root,
436
435
  )
437
436
  match.add_child(_match)
@@ -479,7 +478,7 @@ class RecursiveDescentSelector(JSONPathSelector):
479
478
  obj=val,
480
479
  parent=match,
481
480
  parts=match.parts + (key,),
482
- path=match.path + f"['{key}']",
481
+ path=match.path + f"[{canonical_string(key)}]",
483
482
  root=match.root,
484
483
  )
485
484
  match.add_child(_match)
@@ -633,7 +632,7 @@ class Filter(JSONPathSelector):
633
632
  obj=val,
634
633
  parent=match,
635
634
  parts=match.parts + (key,),
636
- path=match.path + f"['{key}']",
635
+ path=match.path + f"[{canonical_string(key)}]",
637
636
  root=match.root,
638
637
  )
639
638
  match.add_child(_match)
@@ -701,7 +700,7 @@ class Filter(JSONPathSelector):
701
700
  obj=val,
702
701
  parent=match,
703
702
  parts=match.parts + (key,),
704
- path=match.path + f"['{key}']",
703
+ path=match.path + f"[{canonical_string(key)}]",
705
704
  root=match.root,
706
705
  )
707
706
  match.add_child(_match)
jsonpath/serialize.py ADDED
@@ -0,0 +1,13 @@
1
+ """Helper functions for serializing compiled JSONPath queries."""
2
+
3
+ import json
4
+
5
+
6
+ def canonical_string(value: str) -> str:
7
+ """Return _value_ as a canonically formatted string literal."""
8
+ single_quoted = (
9
+ json.dumps(value, ensure_ascii=False)[1:-1]
10
+ .replace('\\"', '"')
11
+ .replace("'", "\\'")
12
+ )
13
+ return f"'{single_quoted}'"
@@ -1,12 +1,13 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: python-jsonpath
3
- Version: 1.2.2
3
+ Version: 1.3.1
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
7
7
  Project-URL: Source, https://github.com/jg-rp/python-jsonpath
8
8
  Author-email: James Prior <jamesgr.prior@gmail.com>
9
- License: MIT
9
+ License-Expression: MIT
10
+ License-File: LICENSE.txt
10
11
  Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Intended Audience :: Developers
12
13
  Classifier: License :: OSI Approved :: MIT License
@@ -96,6 +97,8 @@ conda install -c conda-forge python-jsonpath
96
97
 
97
98
  - [JSON P3](https://github.com/jg-rp/json-p3) - RFC 9535 implemented in TypeScript. JSON P3 does not include all the non-standard features of Python JSONPath, but does define some optional [extra syntax](https://jg-rp.github.io/json-p3/guides/jsonpath-extra).
98
99
 
100
+ - [Ruby JSON P3](https://github.com/jg-rp/ruby-json-p3) - RFC 9535, RFC 6901 and RFC 6902 implemented in Ruby.
101
+
99
102
  ## Examples
100
103
 
101
104
  ### JSONPath
@@ -1,24 +1,25 @@
1
- jsonpath/__about__.py,sha256=_iZoSz5H1QL_IGahln1eJLDPeCpxCbG73dj16UsIHNM,132
2
- jsonpath/__init__.py,sha256=bhEkdyCEv_5MS9J-VyMSRAyIRc-jmKFjLee8-3SYQ3U,2368
1
+ jsonpath/__about__.py,sha256=gvEMxyEUsNjYzzau44eiB6YzOhHDm8YRiKAjgKjAExk,132
2
+ jsonpath/__init__.py,sha256=RTvhFGRb7yLLPUe80a6qD2WAv9gXRe5J69kx0-K6HXc,2412
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
6
  jsonpath/env.py,sha256=EqlLT6_WE7WbChNs_xDipF7V8uGG3EnyKabJ_bstpGs,22815
7
7
  jsonpath/exceptions.py,sha256=5n-9vaKTu5asWllHT0IN-824ewcNCyQIyKvQ58TERVk,4351
8
- jsonpath/filter.py,sha256=b2s_QXjZvcefh7LfDTqSHM-hM5VYy4bpjn1IQRAjeO8,20637
8
+ jsonpath/filter.py,sha256=hat_VU2aXXGUyb7QEYpziW2YRx1DkbJhRCFP_lEPI0M,22051
9
9
  jsonpath/fluent_api.py,sha256=mfAA2t-xUGOmGVr_1h9lxo3y4FsAvaxOpvOH8jZ4DHU,9117
10
10
  jsonpath/lex.py,sha256=8yrSLd3Q3A9Y4GeacOjboUp40XsR_BkRDQ3CC3UVcP8,10296
11
- jsonpath/match.py,sha256=b8fkPHsYjJSrTEOi68MFEyOCj0-FoQjFmMq-Ex4qvo0,3503
11
+ jsonpath/match.py,sha256=qJ8IUn8RsuC-iL6RKr2vTn0l1f7bcx1m9cnZiAEqYH0,3657
12
12
  jsonpath/parse.py,sha256=s7BuFsSgX2GuDubrFr-SDcCk2ZInGzPV04FNFcUwxPM,25214
13
- jsonpath/patch.py,sha256=tSr8-cGOY4lgnSX1PTYotObIZfakbTRaktrO4M4dqgQ,25321
13
+ jsonpath/patch.py,sha256=T6CP0GDJg6drD9qWs6ueRFdQRhXj_xPGEtW5x01iJb8,25388
14
14
  jsonpath/path.py,sha256=RUeP7k_WcvP5ZnYblcRDd_-wgo9VnMKyIevTcRImYE4,16421
15
- jsonpath/pointer.py,sha256=v8k16orIFFOHY1q_QRa5dj4gtPKA--YLA9srOLZpK_E,22299
15
+ jsonpath/pointer.py,sha256=ERoBZvw5QlA7aRaecRTYPiQRFLbwTBe41deguJVOf0k,22392
16
16
  jsonpath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- jsonpath/selectors.py,sha256=u7YcHBt_yEQv0CeTtsOwVQuP5bHLT0_lnulUwShCKdQ,27370
17
+ jsonpath/selectors.py,sha256=oesy964W8Qd1qSSb0qtWJY63A2D0lZc0ppF-pGEYmgU,27313
18
+ jsonpath/serialize.py,sha256=viMcWY52wkUseTNfPKillVWswHePJ2L_B3PV3bDVvmU,360
18
19
  jsonpath/stream.py,sha256=S1xxgOsJlivu6Y8-kejMoYm7MgSlhjnoX_H5cem5Yhk,2815
19
20
  jsonpath/token.py,sha256=2xD2Wrxj7TgyREUhQxzcBcOWLhjz8demYBJ7BqaNJMA,3938
20
21
  jsonpath/function_extensions/__init__.py,sha256=wrUayhwlm6iNLnSIx_ER6EeGiqR91T_SIjNBUr42nX0,548
21
- jsonpath/function_extensions/arguments.py,sha256=whu8c76HGi5Bdj9U39hF71XGoRXpzwdUWmLw6Aumno8,1700
22
+ jsonpath/function_extensions/arguments.py,sha256=gldld_5YHBEWRsZ5jDj9sDm3qj8i6O_8PlOQ3hdH0WU,1696
22
23
  jsonpath/function_extensions/count.py,sha256=FzTOkOLa01PFFSR1wjkDEOyBr_ZC_6yrNfFyGgx7NAk,581
23
24
  jsonpath/function_extensions/filter_function.py,sha256=B6z-02xO6CtNghLN92Acr_UmeiWwJaRDLCOTMcPOrfg,834
24
25
  jsonpath/function_extensions/is_instance.py,sha256=qm9m3UpKJew7qsuSQ5dEem7Ybo4jhCM1uf12wre0SRg,1760
@@ -28,8 +29,8 @@ jsonpath/function_extensions/match.py,sha256=KjsH33fCFGonp2RV__FuaeIOTwLLcvgaaCi
28
29
  jsonpath/function_extensions/search.py,sha256=O11fnkHlbvf0QPrLISYfhlPXBvVPBr-U8V0dGbd614Y,710
29
30
  jsonpath/function_extensions/typeof.py,sha256=yCAj9zOqSnam1mfHCGolNHWDmsBOvU3rAhbZDYycx50,1780
30
31
  jsonpath/function_extensions/value.py,sha256=fQMbPUV87Jn1nOwAlBpTeLmLIG5ejH0XQBOM_SR-Us4,721
31
- python_jsonpath-1.2.2.dist-info/METADATA,sha256=Mn-V3WnVVD-_id7rRuc5PH0e4bNfmJXVTX10LoRx4Ec,6344
32
- python_jsonpath-1.2.2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
33
- python_jsonpath-1.2.2.dist-info/entry_points.txt,sha256=xvbWnAebJyOMI_9ugK0xrpFRlwmEsAJD2kNHU0Dvscc,43
34
- python_jsonpath-1.2.2.dist-info/licenses/LICENSE.txt,sha256=u7PksAQGI1QYWcERHeauMseZ4XAzDKUrKW8Z4wbeU1k,1101
35
- python_jsonpath-1.2.2.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.26.3
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any