python-jsonpath 1.3.2__py3-none-any.whl → 2.0.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 +1 -1
- jsonpath/__init__.py +290 -8
- jsonpath/_types.py +31 -0
- jsonpath/cli.py +11 -1
- jsonpath/env.py +100 -47
- jsonpath/exceptions.py +78 -7
- jsonpath/filter.py +78 -84
- jsonpath/function_extensions/__init__.py +4 -2
- jsonpath/function_extensions/_pattern.py +112 -0
- jsonpath/function_extensions/keys.py +27 -8
- jsonpath/function_extensions/match.py +11 -13
- jsonpath/function_extensions/search.py +11 -13
- jsonpath/function_extensions/starts_with.py +21 -0
- jsonpath/lex.py +113 -64
- jsonpath/lru_cache.py +130 -0
- jsonpath/match.py +13 -0
- jsonpath/parse.py +448 -302
- jsonpath/patch.py +8 -3
- jsonpath/path.py +48 -84
- jsonpath/pointer.py +52 -55
- jsonpath/segments.py +131 -0
- jsonpath/selectors.py +448 -482
- jsonpath/stream.py +68 -70
- jsonpath/token.py +59 -61
- jsonpath/unescape.py +134 -0
- {python_jsonpath-1.3.2.dist-info → python_jsonpath-2.0.1.dist-info}/METADATA +7 -3
- python_jsonpath-2.0.1.dist-info/RECORD +42 -0
- python_jsonpath-1.3.2.dist-info/RECORD +0 -36
- {python_jsonpath-1.3.2.dist-info → python_jsonpath-2.0.1.dist-info}/WHEEL +0 -0
- {python_jsonpath-1.3.2.dist-info → python_jsonpath-2.0.1.dist-info}/entry_points.txt +0 -0
- {python_jsonpath-1.3.2.dist-info → python_jsonpath-2.0.1.dist-info}/licenses/LICENSE.txt +0 -0
jsonpath/stream.py
CHANGED
|
@@ -1,99 +1,97 @@
|
|
|
1
|
-
|
|
1
|
+
"""Step through a stream of tokens."""
|
|
2
|
+
|
|
2
3
|
from __future__ import annotations
|
|
3
4
|
|
|
4
|
-
from
|
|
5
|
-
from typing import Deque
|
|
6
|
-
from typing import Iterator
|
|
5
|
+
from typing import Iterable
|
|
7
6
|
|
|
8
7
|
from .exceptions import JSONPathSyntaxError
|
|
9
8
|
from .token import TOKEN_EOF
|
|
9
|
+
from .token import TOKEN_WHITESPACE
|
|
10
10
|
from .token import Token
|
|
11
11
|
|
|
12
|
-
# ruff: noqa: D102
|
|
13
|
-
|
|
14
12
|
|
|
15
13
|
class TokenStream:
|
|
16
|
-
"""Step through
|
|
17
|
-
|
|
18
|
-
def __init__(self, token_iter:
|
|
19
|
-
self.
|
|
20
|
-
self.
|
|
21
|
-
self.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class TokenStreamIterator:
|
|
25
|
-
"""An iterable token stream."""
|
|
26
|
-
|
|
27
|
-
def __init__(self, stream: TokenStream):
|
|
28
|
-
self.stream = stream
|
|
29
|
-
|
|
30
|
-
def __iter__(self) -> Iterator[Token]:
|
|
31
|
-
return self
|
|
32
|
-
|
|
33
|
-
def __next__(self) -> Token:
|
|
34
|
-
tok = self.stream.current
|
|
35
|
-
if tok.kind is TOKEN_EOF:
|
|
36
|
-
self.stream.close()
|
|
37
|
-
raise StopIteration
|
|
38
|
-
next(self.stream)
|
|
39
|
-
return tok
|
|
40
|
-
|
|
41
|
-
def __iter__(self) -> Iterator[Token]:
|
|
42
|
-
return self.TokenStreamIterator(self)
|
|
43
|
-
|
|
44
|
-
def __next__(self) -> Token:
|
|
45
|
-
tok = self.current
|
|
46
|
-
if self._pushed:
|
|
47
|
-
self.current = self._pushed.popleft()
|
|
48
|
-
elif self.current.kind is not TOKEN_EOF:
|
|
49
|
-
try:
|
|
50
|
-
self.current = next(self.iter)
|
|
51
|
-
except StopIteration:
|
|
52
|
-
self.close()
|
|
53
|
-
return tok
|
|
14
|
+
"""Step through a stream of tokens."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, token_iter: Iterable[Token]):
|
|
17
|
+
self.tokens = list(token_iter)
|
|
18
|
+
self.pos = 0
|
|
19
|
+
path = self.tokens[0].path if self.tokens else ""
|
|
20
|
+
self.eof = Token(TOKEN_EOF, "", -1, path)
|
|
54
21
|
|
|
55
22
|
def __str__(self) -> str: # pragma: no cover
|
|
56
23
|
return f"current: {self.current}\nnext: {self.peek}"
|
|
57
24
|
|
|
58
|
-
def
|
|
59
|
-
"""Return the
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
25
|
+
def current(self) -> Token:
|
|
26
|
+
"""Return the token at the current position in the stream."""
|
|
27
|
+
try:
|
|
28
|
+
return self.tokens[self.pos]
|
|
29
|
+
except IndexError:
|
|
30
|
+
return self.eof
|
|
31
|
+
|
|
32
|
+
def next(self) -> Token:
|
|
33
|
+
"""Return the token at the current position and advance the pointer."""
|
|
34
|
+
try:
|
|
35
|
+
token = self.tokens[self.pos]
|
|
36
|
+
self.pos += 1
|
|
37
|
+
return token
|
|
38
|
+
except IndexError:
|
|
39
|
+
return self.eof
|
|
40
|
+
|
|
41
|
+
def peek(self, offset: int = 1) -> Token:
|
|
42
|
+
"""Return the token at current position plus the offset.
|
|
43
|
+
|
|
44
|
+
Does not advance the pointer.
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
return self.tokens[self.pos + offset]
|
|
48
|
+
except IndexError:
|
|
49
|
+
return self.eof
|
|
50
|
+
|
|
51
|
+
def eat(self, kind: str, message: str | None = None) -> Token:
|
|
52
|
+
"""Assert tge type if the current token and advance the pointer."""
|
|
53
|
+
token = self.next()
|
|
54
|
+
if token.kind != kind:
|
|
55
|
+
raise JSONPathSyntaxError(
|
|
56
|
+
message or f"expected {kind}, found {token.kind!r}",
|
|
57
|
+
token=token,
|
|
58
|
+
)
|
|
59
|
+
return token
|
|
78
60
|
|
|
79
61
|
def expect(self, *typ: str) -> None:
|
|
80
|
-
|
|
62
|
+
"""Raise an exception of the current token is not in `typ`."""
|
|
63
|
+
token = self.current()
|
|
64
|
+
if token.kind not in typ:
|
|
81
65
|
if len(typ) == 1:
|
|
82
66
|
_typ = repr(typ[0])
|
|
83
67
|
else:
|
|
84
68
|
_typ = f"one of {typ!r}"
|
|
85
69
|
raise JSONPathSyntaxError(
|
|
86
|
-
f"expected {_typ}, found {
|
|
87
|
-
token=
|
|
70
|
+
f"expected {_typ}, found {token.kind!r}",
|
|
71
|
+
token=token,
|
|
88
72
|
)
|
|
89
73
|
|
|
90
74
|
def expect_peek(self, *typ: str) -> None:
|
|
91
|
-
|
|
75
|
+
"""Raise an exception of the current token is not in `typ`."""
|
|
76
|
+
token = self.peek()
|
|
77
|
+
if token.kind not in typ:
|
|
92
78
|
if len(typ) == 1:
|
|
93
79
|
_typ = repr(typ[0])
|
|
94
80
|
else:
|
|
95
81
|
_typ = f"one of {typ!r}"
|
|
96
82
|
raise JSONPathSyntaxError(
|
|
97
|
-
f"expected {_typ}, found {
|
|
98
|
-
token=
|
|
83
|
+
f"expected {_typ}, found {token.kind!r}",
|
|
84
|
+
token=token,
|
|
99
85
|
)
|
|
86
|
+
|
|
87
|
+
def expect_peek_not(self, typ: str, message: str) -> None:
|
|
88
|
+
"""Raise an exception if the next token kind of _typ_."""
|
|
89
|
+
if self.peek().kind == typ:
|
|
90
|
+
raise JSONPathSyntaxError(message, token=self.peek())
|
|
91
|
+
|
|
92
|
+
def skip_whitespace(self) -> bool:
|
|
93
|
+
"""Skip whitespace."""
|
|
94
|
+
if self.current().kind == TOKEN_WHITESPACE:
|
|
95
|
+
self.pos += 1
|
|
96
|
+
return True
|
|
97
|
+
return False
|
jsonpath/token.py
CHANGED
|
@@ -1,74 +1,72 @@
|
|
|
1
1
|
"""JSONPath tokens."""
|
|
2
|
+
|
|
2
3
|
import sys
|
|
3
4
|
from typing import Tuple
|
|
4
5
|
|
|
5
6
|
# Utility tokens
|
|
6
|
-
TOKEN_EOF = sys.intern("
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
TOKEN_EOF = sys.intern("TOKEN_EOF")
|
|
8
|
+
TOKEN_WHITESPACE = sys.intern("TOKEN_WHITESPACE")
|
|
9
|
+
TOKEN_ERROR = sys.intern("TOKEN_ERROR")
|
|
9
10
|
|
|
10
11
|
# JSONPath expression tokens
|
|
11
|
-
TOKEN_COLON = sys.intern("
|
|
12
|
-
TOKEN_COMMA = sys.intern("
|
|
13
|
-
TOKEN_DDOT = sys.intern("
|
|
14
|
-
TOKEN_DOT = sys.intern("
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
TOKEN_RBRACKET = sys.intern("
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
TOKEN_SLICE_STEP = sys.intern("SLICE_STEP")
|
|
29
|
-
TOKEN_SLICE_STOP = sys.intern("SLICE_STOP")
|
|
30
|
-
TOKEN_WILD = sys.intern("WILD")
|
|
12
|
+
TOKEN_COLON = sys.intern("TOKEN_COLON")
|
|
13
|
+
TOKEN_COMMA = sys.intern("TOKEN_COMMA")
|
|
14
|
+
TOKEN_DDOT = sys.intern("TOKEN_DDOT")
|
|
15
|
+
TOKEN_DOT = sys.intern("TOKEN_DOT")
|
|
16
|
+
TOKEN_FILTER = sys.intern("TOKEN_FILTER")
|
|
17
|
+
TOKEN_KEY = sys.intern("TOKEN_KEY")
|
|
18
|
+
TOKEN_KEYS = sys.intern("TOKEN_KEYS")
|
|
19
|
+
TOKEN_KEYS_FILTER = sys.intern("TOKEN_KEYS_FILTER")
|
|
20
|
+
TOKEN_LBRACKET = sys.intern("TOKEN_LBRACKET")
|
|
21
|
+
TOKEN_PSEUDO_ROOT = sys.intern("TOKEN_PSEUDO_ROOT")
|
|
22
|
+
TOKEN_RBRACKET = sys.intern("TOKEN_RBRACKET")
|
|
23
|
+
TOKEN_ROOT = sys.intern("TOKEN_ROOT")
|
|
24
|
+
TOKEN_WILD = sys.intern("TOKEN_WILD")
|
|
25
|
+
TOKEN_NAME = sys.intern("TOKEN_NAME")
|
|
26
|
+
TOKEN_DOT_PROPERTY = sys.intern("TOKEN_DOT_PROPERTY")
|
|
27
|
+
TOKEN_DOT_KEY_PROPERTY = sys.intern("TOKEN_DOT_KEY_PROPERTY")
|
|
28
|
+
TOKEN_KEY_NAME = sys.intern("TOKEN_KEY_NAME")
|
|
31
29
|
|
|
32
30
|
# Filter expression tokens
|
|
33
|
-
TOKEN_AND = sys.intern("
|
|
34
|
-
TOKEN_BLANK = sys.intern("
|
|
35
|
-
TOKEN_CONTAINS = sys.intern("
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
TOKEN_FLOAT = sys.intern("
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
TOKEN_SINGLE_QUOTE_STRING = sys.intern("
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
31
|
+
TOKEN_AND = sys.intern("TOKEN_AND")
|
|
32
|
+
TOKEN_BLANK = sys.intern("TOKEN_BLANK")
|
|
33
|
+
TOKEN_CONTAINS = sys.intern("TOKEN_CONTAINS")
|
|
34
|
+
TOKEN_DOUBLE_QUOTE_STRING = sys.intern("TOKEN_DOUBLE_QUOTE_STRING")
|
|
35
|
+
TOKEN_EMPTY = sys.intern("TOKEN_EMPTY")
|
|
36
|
+
TOKEN_EQ = sys.intern("TOKEN_EQ")
|
|
37
|
+
TOKEN_FALSE = sys.intern("TOKEN_FALSE")
|
|
38
|
+
TOKEN_FILTER_CONTEXT = sys.intern("TOKEN_FILTER_CONTEXT")
|
|
39
|
+
TOKEN_FLOAT = sys.intern("TOKEN_FLOAT")
|
|
40
|
+
TOKEN_FUNCTION = sys.intern("TOKEN_FUNCTION")
|
|
41
|
+
TOKEN_GE = sys.intern("TOKEN_GE")
|
|
42
|
+
TOKEN_GT = sys.intern("TOKEN_GT")
|
|
43
|
+
TOKEN_IN = sys.intern("TOKEN_IN")
|
|
44
|
+
TOKEN_INT = sys.intern("TOKEN_INT")
|
|
45
|
+
TOKEN_LE = sys.intern("TOKEN_LE")
|
|
46
|
+
TOKEN_LG = sys.intern("TOKEN_LG")
|
|
47
|
+
TOKEN_LPAREN = sys.intern("TOKEN_LPAREN")
|
|
48
|
+
TOKEN_LT = sys.intern("TOKEN_LT")
|
|
49
|
+
TOKEN_MISSING = sys.intern("TOKEN_MISSING")
|
|
50
|
+
TOKEN_NE = sys.intern("TOKEN_NE")
|
|
51
|
+
TOKEN_NIL = sys.intern("TOKEN_NIL")
|
|
52
|
+
TOKEN_NONE = sys.intern("TOKEN_NONE")
|
|
53
|
+
TOKEN_NOT = sys.intern("TOKEN_NOT")
|
|
54
|
+
TOKEN_NULL = sys.intern("TOKEN_NULL")
|
|
55
|
+
TOKEN_OP = sys.intern("TOKEN_OP")
|
|
56
|
+
TOKEN_OR = sys.intern("TOKEN_OR")
|
|
57
|
+
TOKEN_RE = sys.intern("TOKEN_RE")
|
|
58
|
+
TOKEN_RE_FLAGS = sys.intern("TOKEN_RE_FLAGS")
|
|
59
|
+
TOKEN_RE_PATTERN = sys.intern("TOKEN_RE_PATTERN")
|
|
60
|
+
TOKEN_RPAREN = sys.intern("TOKEN_RPAREN")
|
|
61
|
+
TOKEN_SELF = sys.intern("TOKEN_SELF")
|
|
62
|
+
TOKEN_SINGLE_QUOTE_STRING = sys.intern("TOKEN_SINGLE_QUOTE_STRING")
|
|
63
|
+
TOKEN_STRING = sys.intern("TOKEN_STRING")
|
|
64
|
+
TOKEN_TRUE = sys.intern("TOKEN_TRUE")
|
|
65
|
+
TOKEN_UNDEFINED = sys.intern("TOKEN_UNDEFINED")
|
|
68
66
|
|
|
69
67
|
# Extension tokens
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
TOKEN_INTERSECTION = sys.intern("TOKEN_INTERSECTION")
|
|
69
|
+
TOKEN_UNION = sys.intern("TOKEN_UNION")
|
|
72
70
|
|
|
73
71
|
|
|
74
72
|
class Token:
|
|
@@ -99,7 +97,7 @@ class Token:
|
|
|
99
97
|
|
|
100
98
|
def __repr__(self) -> str: # pragma: no cover
|
|
101
99
|
return (
|
|
102
|
-
f"Token(kind={self.kind
|
|
100
|
+
f"Token(kind={self.kind}, value={self.value!r}, "
|
|
103
101
|
f"index={self.index}, path={self.path!r})"
|
|
104
102
|
)
|
|
105
103
|
|
jsonpath/unescape.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
r"""Replace `\uXXXX` escape sequences with Unicode code points."""
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
from typing import Tuple
|
|
5
|
+
|
|
6
|
+
from .exceptions import JSONPathSyntaxError
|
|
7
|
+
from .token import Token
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def unescape_string(value: str, token: Token, quote: str) -> str:
|
|
11
|
+
"""Return `value` with escape sequences replaced with Unicode code points."""
|
|
12
|
+
unescaped: List[str] = []
|
|
13
|
+
index = 0
|
|
14
|
+
|
|
15
|
+
while index < len(value):
|
|
16
|
+
ch = value[index]
|
|
17
|
+
if ch == "\\":
|
|
18
|
+
index += 1
|
|
19
|
+
_ch, index = _decode_escape_sequence(value, index, token, quote)
|
|
20
|
+
unescaped.append(_ch)
|
|
21
|
+
else:
|
|
22
|
+
_string_from_codepoint(ord(ch), token)
|
|
23
|
+
unescaped.append(ch)
|
|
24
|
+
index += 1
|
|
25
|
+
return "".join(unescaped)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _decode_escape_sequence( # noqa: PLR0911
|
|
29
|
+
value: str, index: int, token: Token, quote: str
|
|
30
|
+
) -> Tuple[str, int]:
|
|
31
|
+
try:
|
|
32
|
+
ch = value[index]
|
|
33
|
+
except IndexError as err:
|
|
34
|
+
raise JSONPathSyntaxError("incomplete escape sequence", token=token) from err
|
|
35
|
+
|
|
36
|
+
if ch == quote:
|
|
37
|
+
return quote, index
|
|
38
|
+
if ch == "\\":
|
|
39
|
+
return "\\", index
|
|
40
|
+
if ch == "/":
|
|
41
|
+
return "/", index
|
|
42
|
+
if ch == "b":
|
|
43
|
+
return "\x08", index
|
|
44
|
+
if ch == "f":
|
|
45
|
+
return "\x0c", index
|
|
46
|
+
if ch == "n":
|
|
47
|
+
return "\n", index
|
|
48
|
+
if ch == "r":
|
|
49
|
+
return "\r", index
|
|
50
|
+
if ch == "t":
|
|
51
|
+
return "\t", index
|
|
52
|
+
if ch == "u":
|
|
53
|
+
codepoint, index = _decode_hex_char(value, index, token)
|
|
54
|
+
return _string_from_codepoint(codepoint, token), index
|
|
55
|
+
|
|
56
|
+
raise JSONPathSyntaxError(
|
|
57
|
+
f"unknown escape sequence at index {token.index + index - 1}",
|
|
58
|
+
token=token,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _decode_hex_char(value: str, index: int, token: Token) -> Tuple[int, int]:
|
|
63
|
+
length = len(value)
|
|
64
|
+
|
|
65
|
+
if index + 4 >= length:
|
|
66
|
+
raise JSONPathSyntaxError(
|
|
67
|
+
f"incomplete escape sequence at index {token.index + index - 1}",
|
|
68
|
+
token=token,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
index += 1 # move past 'u'
|
|
72
|
+
codepoint = _parse_hex_digits(value[index : index + 4], token)
|
|
73
|
+
|
|
74
|
+
if _is_low_surrogate(codepoint):
|
|
75
|
+
raise JSONPathSyntaxError(
|
|
76
|
+
f"unexpected low surrogate at index {token.index + index - 1}",
|
|
77
|
+
token=token,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if _is_high_surrogate(codepoint):
|
|
81
|
+
# expect a surrogate pair
|
|
82
|
+
if not (
|
|
83
|
+
index + 9 < length and value[index + 4] == "\\" and value[index + 5] == "u"
|
|
84
|
+
):
|
|
85
|
+
raise JSONPathSyntaxError(
|
|
86
|
+
f"incomplete escape sequence at index {token.index + index - 2}",
|
|
87
|
+
token=token,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
low_surrogate = _parse_hex_digits(value[index + 6 : index + 10], token)
|
|
91
|
+
|
|
92
|
+
if not _is_low_surrogate(low_surrogate):
|
|
93
|
+
raise JSONPathSyntaxError(
|
|
94
|
+
f"unexpected codepoint at index {token.index + index + 4}",
|
|
95
|
+
token=token,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
codepoint = 0x10000 + (((codepoint & 0x03FF) << 10) | (low_surrogate & 0x03FF))
|
|
99
|
+
|
|
100
|
+
return (codepoint, index + 9)
|
|
101
|
+
|
|
102
|
+
return (codepoint, index + 3)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _parse_hex_digits(digits: str, token: Token) -> int:
|
|
106
|
+
codepoint = 0
|
|
107
|
+
for digit in digits.encode():
|
|
108
|
+
codepoint <<= 4
|
|
109
|
+
if digit >= 48 and digit <= 57:
|
|
110
|
+
codepoint |= digit - 48
|
|
111
|
+
elif digit >= 65 and digit <= 70:
|
|
112
|
+
codepoint |= digit - 65 + 10
|
|
113
|
+
elif digit >= 97 and digit <= 102:
|
|
114
|
+
codepoint |= digit - 97 + 10
|
|
115
|
+
else:
|
|
116
|
+
raise JSONPathSyntaxError(
|
|
117
|
+
"invalid \\uXXXX escape sequence",
|
|
118
|
+
token=token,
|
|
119
|
+
)
|
|
120
|
+
return codepoint
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _string_from_codepoint(codepoint: int, token: Token) -> str:
|
|
124
|
+
if codepoint <= 0x1F:
|
|
125
|
+
raise JSONPathSyntaxError("invalid character", token=token)
|
|
126
|
+
return chr(codepoint)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _is_high_surrogate(codepoint: int) -> bool:
|
|
130
|
+
return codepoint >= 0xD800 and codepoint <= 0xDBFF
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _is_low_surrogate(codepoint: int) -> bool:
|
|
134
|
+
return codepoint >= 0xDC00 and codepoint <= 0xDFFF
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-jsonpath
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.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
|
|
@@ -8,6 +8,7 @@ Project-URL: Source, https://github.com/jg-rp/python-jsonpath
|
|
|
8
8
|
Author-email: James Prior <jamesgr.prior@gmail.com>
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE.txt
|
|
11
|
+
Keywords: JSON,JSON Patch,JSON Path,JSON Pointer,JSONPath,RFC 9535
|
|
11
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
13
|
Classifier: Intended Audience :: Developers
|
|
13
14
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -21,6 +22,9 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
21
22
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
22
23
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
23
24
|
Requires-Python: >=3.8
|
|
25
|
+
Provides-Extra: strict
|
|
26
|
+
Requires-Dist: iregexp-check>=0.1.4; extra == 'strict'
|
|
27
|
+
Requires-Dist: regex; extra == 'strict'
|
|
24
28
|
Description-Content-Type: text/markdown
|
|
25
29
|
|
|
26
30
|
<h1 align="center">Python JSONPath</h1>
|
|
@@ -91,9 +95,9 @@ conda install -c conda-forge python-jsonpath
|
|
|
91
95
|
|
|
92
96
|
## Related projects
|
|
93
97
|
|
|
94
|
-
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A Python implementation of
|
|
98
|
+
- [JSONPath RFC 9535](https://github.com/jg-rp/python-jsonpath-rfc9535) - A minimal, slightly cleanr Python implementation of RFC 9535. If you're not interested JSONPath sytax beyond that defined in RFC 9535, you might choose [jsonpath-rfc9535](https://pypi.org/project/jsonpath-rfc9535/) over [python-jsonpath](https://pypi.org/project/python-jsonpath/).
|
|
95
99
|
|
|
96
|
-
jsonpath-rfc9535
|
|
100
|
+
jsonpath-rfc9535 also includes utilities for verifying and testing the [JSONPath Compliance Test Suite](https://github.com/jsonpath-standard/jsonpath-compliance-test-suite). Most notably the nondeterministic behavior of some JSONPath selectors.
|
|
97
101
|
|
|
98
102
|
- [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).
|
|
99
103
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
jsonpath/__about__.py,sha256=-7JogzyaEMlAT9mZnAfz6WvYW2e1688bbokpApou5SM,132
|
|
2
|
+
jsonpath/__init__.py,sha256=-a4CE0KwMtXNtOvTIriRZ37EQezZ85EpLz7sj2XpXeQ,11101
|
|
3
|
+
jsonpath/__main__.py,sha256=6Y5wOE7U-MHymopXOsxofaY30tVZYPGTJO0L4vytoUw,61
|
|
4
|
+
jsonpath/_data.py,sha256=JEpu5Kg0_kgxYKUilBcHVdTmPxf3-Vc0NgaW6olsqyY,577
|
|
5
|
+
jsonpath/_types.py,sha256=mxwypalUAI64XdDwXCwIM_1MXCUOTM13y826j-UD8LY,818
|
|
6
|
+
jsonpath/cli.py,sha256=QNDOzRvGWW9jDNhPpsE9tL1jyS9LS5kSQeMh3q86C6E,10217
|
|
7
|
+
jsonpath/env.py,sha256=G0UK9NZvxaLEicdD10hxrd3C_pp-o9FxekkzpZb_O4I,24540
|
|
8
|
+
jsonpath/exceptions.py,sha256=V7A4A76NjFffa11ePEYgYcV6gG8sdmL9fh3KGEGqPu8,6498
|
|
9
|
+
jsonpath/filter.py,sha256=W4TyM8um0AQzA_m4Iy-dr1Jd5341YmTP6UWmXfSpia4,22617
|
|
10
|
+
jsonpath/fluent_api.py,sha256=mfAA2t-xUGOmGVr_1h9lxo3y4FsAvaxOpvOH8jZ4DHU,9117
|
|
11
|
+
jsonpath/lex.py,sha256=_64KcaE5Mi3-E5DdYMyX1tHRHtokQWXGKT-ToMb_dfs,12019
|
|
12
|
+
jsonpath/lru_cache.py,sha256=ohd_ssx2UnBWlLyt16bh2Vg6a_SDA1xHyI_wyOkHLvY,4047
|
|
13
|
+
jsonpath/match.py,sha256=hPz0OEVJOYJ3MzenJuUzxxHSC0-NNPrLyHXHBRYzOZE,4167
|
|
14
|
+
jsonpath/parse.py,sha256=QplaB5u2QRl_MyVUDkJ39cPKI6s2oX-ztZ10KUcxNQM,29973
|
|
15
|
+
jsonpath/patch.py,sha256=pwlAPFlwHZ-gW8COy60Axk9e1yIVNnQ4ctD0IEILaA4,25593
|
|
16
|
+
jsonpath/path.py,sha256=k4LEmfMhNcJ0ZnEIqOX--G1SoCWhtZZ2S1OzC6kHotA,15661
|
|
17
|
+
jsonpath/pointer.py,sha256=VEd_cX2_5eR-z755yRatmIS-OLAl_e-9wZhF-t4F1YM,23037
|
|
18
|
+
jsonpath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
|
+
jsonpath/segments.py,sha256=a3gTT6capn2VTjMLbVUeYgkzNhEMCjcopZh7WkdrGbs,4458
|
|
20
|
+
jsonpath/selectors.py,sha256=ozxKBwd81E3Fd0F-E-9nrPZYqmNLfdrWYjliGfE8jGU,24645
|
|
21
|
+
jsonpath/serialize.py,sha256=viMcWY52wkUseTNfPKillVWswHePJ2L_B3PV3bDVvmU,360
|
|
22
|
+
jsonpath/stream.py,sha256=oAucLnRJWlBgz543oF1o89RsIcZA2zSSOZnlOaE7qd0,3090
|
|
23
|
+
jsonpath/token.py,sha256=fc8fio4pqVyV3cJee79AQlOKEaXpVFJtTAAXfgGFohg,4167
|
|
24
|
+
jsonpath/unescape.py,sha256=CBZawMNDL5VWGKC4BkyocSrv3pCeOtXD6AEIjcMPkFI,3973
|
|
25
|
+
jsonpath/function_extensions/__init__.py,sha256=dcbt-G40PbksRTK1nw7Q8ZYrxiD2xev6wAmh0kiPVcY,602
|
|
26
|
+
jsonpath/function_extensions/_pattern.py,sha256=Ham8k79oWR0CoSgA1M3Wdm9Xw1jkhShFZsYI6-9534I,3267
|
|
27
|
+
jsonpath/function_extensions/arguments.py,sha256=gldld_5YHBEWRsZ5jDj9sDm3qj8i6O_8PlOQ3hdH0WU,1696
|
|
28
|
+
jsonpath/function_extensions/count.py,sha256=FzTOkOLa01PFFSR1wjkDEOyBr_ZC_6yrNfFyGgx7NAk,581
|
|
29
|
+
jsonpath/function_extensions/filter_function.py,sha256=B6z-02xO6CtNghLN92Acr_UmeiWwJaRDLCOTMcPOrfg,834
|
|
30
|
+
jsonpath/function_extensions/is_instance.py,sha256=qm9m3UpKJew7qsuSQ5dEem7Ybo4jhCM1uf12wre0SRg,1760
|
|
31
|
+
jsonpath/function_extensions/keys.py,sha256=-m4MwUvSRN9A1_3LLM3FQaOjKzvbhyGtyn86ph9WPDc,822
|
|
32
|
+
jsonpath/function_extensions/length.py,sha256=Z9gtz0zhzT1_8LzzHm1TRhJlMWT5yEsqNtQCuWg14I0,786
|
|
33
|
+
jsonpath/function_extensions/match.py,sha256=LdVfX7b_AMhwkSMh-kyNogTpI7_neBxOlQuvrZQjO4c,573
|
|
34
|
+
jsonpath/function_extensions/search.py,sha256=H2Si0js_UG6LACxHfZDPhKK8qqmVtUUhr3TY0i3hrkE,573
|
|
35
|
+
jsonpath/function_extensions/starts_with.py,sha256=z-9hkNjQQj_p579CnM6W-E6nc1ucooHHwKwpefO_EBA,676
|
|
36
|
+
jsonpath/function_extensions/typeof.py,sha256=yCAj9zOqSnam1mfHCGolNHWDmsBOvU3rAhbZDYycx50,1780
|
|
37
|
+
jsonpath/function_extensions/value.py,sha256=fQMbPUV87Jn1nOwAlBpTeLmLIG5ejH0XQBOM_SR-Us4,721
|
|
38
|
+
python_jsonpath-2.0.1.dist-info/METADATA,sha256=fyv3QwOwtVsP_9Nkqv-1Cn8Natr-WHF1jd0n9gYFAts,6529
|
|
39
|
+
python_jsonpath-2.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
40
|
+
python_jsonpath-2.0.1.dist-info/entry_points.txt,sha256=xvbWnAebJyOMI_9ugK0xrpFRlwmEsAJD2kNHU0Dvscc,43
|
|
41
|
+
python_jsonpath-2.0.1.dist-info/licenses/LICENSE.txt,sha256=u7PksAQGI1QYWcERHeauMseZ4XAzDKUrKW8Z4wbeU1k,1101
|
|
42
|
+
python_jsonpath-2.0.1.dist-info/RECORD,,
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
jsonpath/__about__.py,sha256=lKzAT7eRQ0XCM36oMem3ZY_sdLarE9W-QFI1Ret5qKc,132
|
|
2
|
-
jsonpath/__init__.py,sha256=WlqHtXZcMy2AnAqvBQeiUcS1_I7Upif2j7SSLYZGTNg,2335
|
|
3
|
-
jsonpath/__main__.py,sha256=6Y5wOE7U-MHymopXOsxofaY30tVZYPGTJO0L4vytoUw,61
|
|
4
|
-
jsonpath/_data.py,sha256=JEpu5Kg0_kgxYKUilBcHVdTmPxf3-Vc0NgaW6olsqyY,577
|
|
5
|
-
jsonpath/cli.py,sha256=scpWfJXl1jLQ80ZyXqMCu8JtRgZUXluC11x6OkC4oeA,10026
|
|
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
|
-
jsonpath/fluent_api.py,sha256=mfAA2t-xUGOmGVr_1h9lxo3y4FsAvaxOpvOH8jZ4DHU,9117
|
|
10
|
-
jsonpath/lex.py,sha256=8yrSLd3Q3A9Y4GeacOjboUp40XsR_BkRDQ3CC3UVcP8,10296
|
|
11
|
-
jsonpath/match.py,sha256=qJ8IUn8RsuC-iL6RKr2vTn0l1f7bcx1m9cnZiAEqYH0,3657
|
|
12
|
-
jsonpath/parse.py,sha256=s7BuFsSgX2GuDubrFr-SDcCk2ZInGzPV04FNFcUwxPM,25214
|
|
13
|
-
jsonpath/patch.py,sha256=T6CP0GDJg6drD9qWs6ueRFdQRhXj_xPGEtW5x01iJb8,25388
|
|
14
|
-
jsonpath/path.py,sha256=RUeP7k_WcvP5ZnYblcRDd_-wgo9VnMKyIevTcRImYE4,16421
|
|
15
|
-
jsonpath/pointer.py,sha256=UjqqWQWL8D-chjSEQ2al_Ev5xcHaKxFFfQxPfuBSwO0,23100
|
|
16
|
-
jsonpath/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
jsonpath/selectors.py,sha256=oesy964W8Qd1qSSb0qtWJY63A2D0lZc0ppF-pGEYmgU,27313
|
|
18
|
-
jsonpath/serialize.py,sha256=viMcWY52wkUseTNfPKillVWswHePJ2L_B3PV3bDVvmU,360
|
|
19
|
-
jsonpath/stream.py,sha256=S1xxgOsJlivu6Y8-kejMoYm7MgSlhjnoX_H5cem5Yhk,2815
|
|
20
|
-
jsonpath/token.py,sha256=2xD2Wrxj7TgyREUhQxzcBcOWLhjz8demYBJ7BqaNJMA,3938
|
|
21
|
-
jsonpath/function_extensions/__init__.py,sha256=wrUayhwlm6iNLnSIx_ER6EeGiqR91T_SIjNBUr42nX0,548
|
|
22
|
-
jsonpath/function_extensions/arguments.py,sha256=gldld_5YHBEWRsZ5jDj9sDm3qj8i6O_8PlOQ3hdH0WU,1696
|
|
23
|
-
jsonpath/function_extensions/count.py,sha256=FzTOkOLa01PFFSR1wjkDEOyBr_ZC_6yrNfFyGgx7NAk,581
|
|
24
|
-
jsonpath/function_extensions/filter_function.py,sha256=B6z-02xO6CtNghLN92Acr_UmeiWwJaRDLCOTMcPOrfg,834
|
|
25
|
-
jsonpath/function_extensions/is_instance.py,sha256=qm9m3UpKJew7qsuSQ5dEem7Ybo4jhCM1uf12wre0SRg,1760
|
|
26
|
-
jsonpath/function_extensions/keys.py,sha256=vNdIV8xqr1LMG6RLJwb6iA5-VXgYSZu6CqprXEs6rYM,364
|
|
27
|
-
jsonpath/function_extensions/length.py,sha256=Z9gtz0zhzT1_8LzzHm1TRhJlMWT5yEsqNtQCuWg14I0,786
|
|
28
|
-
jsonpath/function_extensions/match.py,sha256=KjsH33fCFGonp2RV__FuaeIOTwLLcvgaaCi0juyEl-U,712
|
|
29
|
-
jsonpath/function_extensions/search.py,sha256=O11fnkHlbvf0QPrLISYfhlPXBvVPBr-U8V0dGbd614Y,710
|
|
30
|
-
jsonpath/function_extensions/typeof.py,sha256=yCAj9zOqSnam1mfHCGolNHWDmsBOvU3rAhbZDYycx50,1780
|
|
31
|
-
jsonpath/function_extensions/value.py,sha256=fQMbPUV87Jn1nOwAlBpTeLmLIG5ejH0XQBOM_SR-Us4,721
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|