python-jsonpath
Advanced tools
+6
-1
@@ -80,2 +80,4 @@ # Byte-compiled / optimized / DLL files | ||
| .vscode/ | ||
| .idea/ | ||
| python-jsonpath.iml | ||
@@ -92,2 +94,5 @@ # Dev utils | ||
| # System | ||
| .DS_Store | ||
| .DS_Store | ||
| # Rob-specific | ||
| generated_temp/ |
| # SPDX-FileCopyrightText: 2023-present James Prior <jamesgr.prior@gmail.com> | ||
| # | ||
| # SPDX-License-Identifier: MIT | ||
| __version__ = "1.3.1" | ||
| __version__ = "1.3.2" |
@@ -13,3 +13,2 @@ # SPDX-FileCopyrightText: 2023-present James Prior <jamesgr.prior@gmail.com> | ||
| from .exceptions import JSONPathTypeError | ||
| from .exceptions import JSONPointerEncodeError | ||
| from .exceptions import JSONPointerError | ||
@@ -56,3 +55,2 @@ from .exceptions import JSONPointerIndexError | ||
| "JSONPointer", | ||
| "JSONPointerEncodeError", | ||
| "JSONPointerError", | ||
@@ -59,0 +57,0 @@ "JSONPointerIndexError", |
+1
-1
@@ -102,3 +102,3 @@ """Core JSONPath configuration object.""" | ||
| key_token (str): The pattern used to identify the current key or index when | ||
| filtering a, mapping or sequence. Defaults to `"#"`. | ||
| filtering a mapping or sequence. Defaults to `"#"`. | ||
| keys_selector_token (str): The pattern used as the "keys" selector. Defaults to | ||
@@ -105,0 +105,0 @@ `"~"`. |
| """JSONPath exceptions.""" | ||
| from __future__ import annotations | ||
@@ -83,6 +84,2 @@ | ||
| class JSONPointerEncodeError(JSONPointerError): | ||
| """An exception raised when a JSONPathMatch can't be encoded to a JSON Pointer.""" | ||
| class JSONPointerResolutionError(JSONPointerError): | ||
@@ -149,3 +146,3 @@ """Base exception for those that can be raised during pointer resolution.""" | ||
| return value | ||
| return f"{value[:num-len(end)]}{end}" | ||
| return f"{value[: num - len(end)]}{end}" | ||
@@ -152,0 +149,0 @@ |
+36
-6
@@ -547,3 +547,8 @@ """Filter expression nodes.""" | ||
| return NodeList(self.path.finditer(context.current)) | ||
| return NodeList( | ||
| self.path.finditer( | ||
| context.current, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ) | ||
@@ -561,3 +566,9 @@ async def evaluate_async(self, context: FilterContext) -> object: | ||
| return NodeList( | ||
| [match async for match in await self.path.finditer_async(context.current)] | ||
| [ | ||
| match | ||
| async for match in await self.path.finditer_async( | ||
| context.current, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ] | ||
| ) | ||
@@ -581,7 +592,18 @@ | ||
| def evaluate(self, context: FilterContext) -> object: | ||
| return NodeList(self.path.finditer(context.root)) | ||
| return NodeList( | ||
| self.path.finditer( | ||
| context.root, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ) | ||
| async def evaluate_async(self, context: FilterContext) -> object: | ||
| return NodeList( | ||
| [match async for match in await self.path.finditer_async(context.root)] | ||
| [ | ||
| match | ||
| async for match in await self.path.finditer_async( | ||
| context.root, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ] | ||
| ) | ||
@@ -606,3 +628,8 @@ | ||
| def evaluate(self, context: FilterContext) -> object: | ||
| return NodeList(self.path.finditer(context.extra_context)) | ||
| return NodeList( | ||
| self.path.finditer( | ||
| context.extra_context, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ) | ||
@@ -613,3 +640,6 @@ async def evaluate_async(self, context: FilterContext) -> object: | ||
| match | ||
| async for match in await self.path.finditer_async(context.extra_context) | ||
| async for match in await self.path.finditer_async( | ||
| context.extra_context, | ||
| filter_context=context.extra_context, | ||
| ) | ||
| ] | ||
@@ -616,0 +646,0 @@ ) |
+71
-47
@@ -35,3 +35,3 @@ """JSON Pointer. See https://datatracker.ietf.org/doc/html/rfc6901.""" | ||
| def __str__(self) -> str: | ||
| return "<jsonpath.pointer.UNDEFINED>" | ||
| return "<jsonpath.pointer.UNDEFINED>" # pragma: no cover | ||
@@ -119,3 +119,3 @@ | ||
| if index < self.min_int_index or index > self.max_int_index: | ||
| raise JSONPointerIndexError("index out of range") | ||
| raise JSONPointerError("index out of range") | ||
| return index | ||
@@ -125,50 +125,74 @@ except ValueError: | ||
| def _getitem(self, obj: Any, key: Any) -> Any: # noqa: PLR0912 | ||
| def _getitem(self, obj: Any, key: Any) -> Any: | ||
| try: | ||
| # Handle the most common cases. A mapping with a string key, or a sequence | ||
| # with an integer index. | ||
| # | ||
| # Note that `obj` does not have to be a Mapping or Sequence here. Any object | ||
| # implementing `__getitem__` will do. | ||
| return getitem(obj, key) | ||
| except KeyError as err: | ||
| # Try a string repr of the index-like item as a mapping key. | ||
| if isinstance(key, int): | ||
| try: | ||
| return getitem(obj, str(key)) | ||
| except KeyError: | ||
| raise JSONPointerKeyError(key) from err | ||
| # Handle non-standard keys/property selector/pointer. | ||
| if ( | ||
| isinstance(key, str) | ||
| and isinstance(obj, Mapping) | ||
| and key.startswith((self.keys_selector, "#")) | ||
| and key[1:] in obj | ||
| ): | ||
| return key[1:] | ||
| # Handle non-standard index/property pointer (`#`) | ||
| raise JSONPointerKeyError(key) from err | ||
| return self._handle_key_error(obj, key, err) | ||
| except TypeError as err: | ||
| if isinstance(obj, Sequence) and not isinstance(obj, str): | ||
| if key == "-": | ||
| # "-" is a valid index when appending to a JSON array | ||
| # with JSON Patch, but not when resolving a JSON Pointer. | ||
| raise JSONPointerIndexError("index out of range") from None | ||
| # Handle non-standard index pointer. | ||
| if isinstance(key, str) and key.startswith("#"): | ||
| _index = int(key[1:]) | ||
| if _index >= len(obj): | ||
| raise JSONPointerIndexError( | ||
| f"index out of range: {_index}" | ||
| ) from err | ||
| return _index | ||
| # Try int index. Reject non-zero ints that start with a zero. | ||
| if isinstance(key, str): | ||
| index = self._index(key) | ||
| if isinstance(index, int): | ||
| try: | ||
| return getitem(obj, int(key)) | ||
| except IndexError as index_err: | ||
| raise JSONPointerIndexError( | ||
| f"index out of range: {key}" | ||
| ) from index_err | ||
| raise JSONPointerTypeError(f"{key}: {err}") from err | ||
| return self._handle_type_error(obj, key, err) | ||
| except IndexError as err: | ||
| raise JSONPointerIndexError(f"index out of range: {key}") from err | ||
| def _handle_key_error(self, obj: Any, key: Any, err: Exception) -> object: | ||
| if isinstance(key, int): | ||
| # Try a string repr of the index-like item as a mapping key. | ||
| return self._getitem(obj, str(key)) | ||
| # Handle non-standard key/property selector/pointer. | ||
| # | ||
| # For the benefit of `RelativeJSONPointer.to()` and `JSONPathMatch.pointer()`, | ||
| # treat keys starting with a `#` or `~` as a "key pointer". If `key[1:]` is a | ||
| # key in `obj`, return the key. | ||
| # | ||
| # Note that if a key with a leading `#`/`~` exists in `obj`, it will have been | ||
| # handled by `_getitem`. | ||
| if ( | ||
| isinstance(key, str) | ||
| and isinstance(obj, Mapping) | ||
| and key.startswith((self.keys_selector, "#")) | ||
| and key[1:] in obj | ||
| ): | ||
| return key[1:] | ||
| raise JSONPointerKeyError(key) from err | ||
| def _handle_type_error(self, obj: Any, key: Any, err: Exception) -> object: | ||
| if ( | ||
| isinstance(obj, str) | ||
| or not isinstance(obj, Sequence) | ||
| or not isinstance(key, str) | ||
| ): | ||
| raise JSONPointerTypeError(f"{key}: {err}") from err | ||
| # `obj` is array-like | ||
| # `key` is a string | ||
| if key == "-": | ||
| # "-" is a valid index when appending to a JSON array with JSON Patch, but | ||
| # not when resolving a JSON Pointer. | ||
| raise JSONPointerIndexError("index out of range") from None | ||
| # Handle non-standard index pointer. | ||
| # | ||
| # For the benefit of `RelativeJSONPointer.to()`, treat keys starting with a `#` | ||
| # and followed by a valid index as an "index pointer". If `int(key[1:])` is | ||
| # less than `len(obj)`, return the index. | ||
| if re.match(r"#[1-9]\d*", key): | ||
| _index = int(key[1:]) | ||
| if _index >= len(obj): | ||
| raise JSONPointerIndexError(f"index out of range: {_index}") from err | ||
| return _index | ||
| # Try int index. Reject non-zero ints that start with a zero. | ||
| index = self._index(key) | ||
| if isinstance(index, int): | ||
| return self._getitem(obj, index) | ||
| raise JSONPointerTypeError(f"{key}: {err}") from err | ||
| def resolve( | ||
@@ -269,3 +293,3 @@ self, | ||
| # This should not happen, unless the JSONPathMatch has been tampered with. | ||
| pointer = "" | ||
| pointer = "" # pragma: no cover | ||
@@ -335,6 +359,6 @@ return cls( | ||
| def __hash__(self) -> int: | ||
| return hash(self.parts) | ||
| return hash(self.parts) # pragma: no cover | ||
| def __repr__(self) -> str: | ||
| return f"JSONPointer({self._s!r})" | ||
| return f"JSONPointer({self._s!r})" # pragma: no cover | ||
@@ -494,3 +518,3 @@ def exists( | ||
| def __hash__(self) -> int: | ||
| return hash((self.origin, self.index, self.pointer)) | ||
| return hash((self.origin, self.index, self.pointer)) # pragma: no cover | ||
@@ -497,0 +521,0 @@ def _parse( |
+1
-1
| Metadata-Version: 2.4 | ||
| Name: python-jsonpath | ||
| Version: 1.3.1 | ||
| Version: 1.3.2 | ||
| Summary: JSONPath, JSON Pointer and JSON Patch for Python. | ||
@@ -5,0 +5,0 @@ Project-URL: Documentation, https://jg-rp.github.io/python-jsonpath/ |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
239048
0.53%5483
0.75%