python-jsonpath 0.10.2__tar.gz → 0.10.3__tar.gz

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.
Files changed (34) hide show
  1. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/PKG-INFO +4 -1
  2. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/README.md +3 -0
  3. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/__about__.py +1 -1
  4. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/filter.py +13 -1
  5. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/length.py +10 -4
  6. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/parse.py +14 -25
  7. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/.gitignore +0 -0
  8. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/LICENSE.txt +0 -0
  9. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/__init__.py +0 -0
  10. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/__main__.py +0 -0
  11. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/_data.py +0 -0
  12. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/cli.py +0 -0
  13. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/env.py +0 -0
  14. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/exceptions.py +0 -0
  15. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/__init__.py +0 -0
  16. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/arguments.py +0 -0
  17. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/count.py +0 -0
  18. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/filter_function.py +0 -0
  19. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/is_instance.py +0 -0
  20. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/keys.py +0 -0
  21. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/match.py +0 -0
  22. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/search.py +0 -0
  23. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/typeof.py +0 -0
  24. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/function_extensions/value.py +0 -0
  25. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/lex.py +0 -0
  26. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/match.py +0 -0
  27. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/patch.py +0 -0
  28. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/path.py +0 -0
  29. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/pointer.py +0 -0
  30. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/py.typed +0 -0
  31. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/selectors.py +0 -0
  32. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/stream.py +0 -0
  33. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/jsonpath/token.py +0 -0
  34. {python_jsonpath-0.10.2 → python_jsonpath-0.10.3}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-jsonpath
3
- Version: 0.10.2
3
+ Version: 0.10.3
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
@@ -36,6 +36,9 @@ A flexible JSONPath engine for Python with JSON Pointer and JSON Patch.
36
36
  <a href="https://github.com/jg-rp/python-jsonpath/actions">
37
37
  <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/python-jsonpath/tests.yaml?branch=main&label=tests&style=flat-square" alt="Tests">
38
38
  </a>
39
+ <a href="https://pypi.org/project/python-jsonpath">
40
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-jsonpath?style=flat-square">
41
+ </a>
39
42
  <br>
40
43
  <a href="https://pypi.org/project/python-jsonpath">
41
44
  <img src="https://img.shields.io/pypi/v/python-jsonpath.svg?style=flat-square" alt="PyPi - Version">
@@ -11,6 +11,9 @@ A flexible JSONPath engine for Python with JSON Pointer and JSON Patch.
11
11
  <a href="https://github.com/jg-rp/python-jsonpath/actions">
12
12
  <img src="https://img.shields.io/github/actions/workflow/status/jg-rp/python-jsonpath/tests.yaml?branch=main&label=tests&style=flat-square" alt="Tests">
13
13
  </a>
14
+ <a href="https://pypi.org/project/python-jsonpath">
15
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/python-jsonpath?style=flat-square">
16
+ </a>
14
17
  <br>
15
18
  <a href="https://pypi.org/project/python-jsonpath">
16
19
  <img src="https://img.shields.io/pypi/v/python-jsonpath.svg?style=flat-square" alt="PyPi - Version">
@@ -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__ = "0.10.2"
4
+ __version__ = "0.10.3"
@@ -623,7 +623,19 @@ class FunctionExtension(FilterExpression):
623
623
  if func.arg_types[idx] != ExpressionType.NODES and isinstance(
624
624
  arg, NodeList
625
625
  ):
626
- _args.append(arg.values_or_singular())
626
+ if len(arg) == 0:
627
+ # If the query results in an empty nodelist, the
628
+ # argument is the special result Nothing.
629
+ _args.append(UNDEFINED)
630
+ elif len(arg) == 1:
631
+ # If the query results in a nodelist consisting of a
632
+ # single node, the argument is the value of the node
633
+ _args.append(arg[0].obj)
634
+ else:
635
+ # This should not be possible as a non-singular query
636
+ # would have been rejected when checking function
637
+ # well-typedness.
638
+ _args.append(arg)
627
639
  else:
628
640
  _args.append(arg)
629
641
  return _args
@@ -1,7 +1,9 @@
1
1
  """The standard `length` function extension."""
2
2
  from collections.abc import Sized
3
- from typing import Optional
3
+ from typing import Union
4
4
 
5
+ from jsonpath.filter import UNDEFINED
6
+ from jsonpath.filter import _Undefined
5
7
  from jsonpath.function_extensions import ExpressionType
6
8
  from jsonpath.function_extensions import FilterFunction
7
9
 
@@ -12,9 +14,13 @@ class Length(FilterFunction):
12
14
  arg_types = [ExpressionType.VALUE]
13
15
  return_type = ExpressionType.VALUE
14
16
 
15
- def __call__(self, obj: Sized) -> Optional[int]:
16
- """Return an object's length, or `None` if the object does not have a length."""
17
+ def __call__(self, obj: Sized) -> Union[int, _Undefined]:
18
+ """Return an object's length.
19
+
20
+ If the object does not have a length, the special _Nothing_ value is
21
+ returned.
22
+ """
17
23
  try:
18
24
  return len(obj)
19
25
  except TypeError:
20
- return None
26
+ return UNDEFINED
@@ -180,7 +180,7 @@ class Parser:
180
180
  TOKEN_RE: "=~",
181
181
  }
182
182
 
183
- SINGULAR_QUERY_COMPARISON_OPERATORS = frozenset(
183
+ COMPARISON_OPERATORS = frozenset(
184
184
  [
185
185
  "==",
186
186
  ">=",
@@ -511,10 +511,7 @@ class Parser:
511
511
  right = self.parse_filter_selector(stream, precedence)
512
512
  operator = self.BINARY_OPERATORS[tok.kind]
513
513
 
514
- self._raise_for_non_singular_query(left, tok) # TODO: store tok on expression
515
- self._raise_for_non_singular_query(right, tok)
516
-
517
- if operator in self.SINGULAR_QUERY_COMPARISON_OPERATORS:
514
+ if self.env.well_typed and operator in self.COMPARISON_OPERATORS:
518
515
  self._raise_for_non_comparable_function(left, tok)
519
516
  self._raise_for_non_comparable_function(right, tok)
520
517
 
@@ -666,26 +663,18 @@ class Parser:
666
663
 
667
664
  return token.value
668
665
 
669
- def _raise_for_non_singular_query(
670
- self, expr: FilterExpression, token: Token
671
- ) -> None:
672
- if (
673
- self.env.well_typed
674
- and isinstance(expr, Path)
675
- and not expr.path.singular_query()
676
- ):
677
- raise JSONPathSyntaxError(
678
- "non-singular query is not comparable", token=token
679
- )
680
-
681
666
  def _raise_for_non_comparable_function(
682
667
  self, expr: FilterExpression, token: Token
683
668
  ) -> None:
684
- if not self.env.well_typed or not isinstance(expr, FunctionExtension):
685
- return
686
- func = self.env.function_extensions.get(expr.name)
687
- if (
688
- isinstance(func, FilterFunction)
689
- and func.return_type != ExpressionType.VALUE
690
- ):
691
- raise JSONPathTypeError(f"result of {expr.name}() is not comparable", token)
669
+ if isinstance(expr, Path) and not expr.path.singular_query():
670
+ raise JSONPathTypeError("non-singular query is not comparable", token=token)
671
+
672
+ if isinstance(expr, FunctionExtension):
673
+ func = self.env.function_extensions.get(expr.name)
674
+ if (
675
+ isinstance(func, FilterFunction)
676
+ and func.return_type != ExpressionType.VALUE
677
+ ):
678
+ raise JSONPathTypeError(
679
+ f"result of {expr.name}() is not comparable", token
680
+ )