Skip to content

Commit

Permalink
Fix parsing of scientific notation in JSONPath queries
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Sep 28, 2023
1 parent 65c8920 commit f2bc762
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
**Fixes**

- We no longer silently ignore invalid escape sequences in JSONPath string literals. For example, `$['\"']` used to be OK, it now raises a `JSONPathSyntaxError`.
- Fixed parsing of JSONPath integer literals that use scientific notation.

## Version 0.9.0

Expand Down
15 changes: 14 additions & 1 deletion jsonpath/lex.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def compile_rules(self) -> Pattern[str]:
(TOKEN_BRACKET_PROPERTY, self.bracketed_property_pattern),
(TOKEN_DOT_PROPERTY, self.dot_property_pattern),
(TOKEN_FLOAT, r"-?\d+\.\d*(?:e[+-]?\d+)?"),
(TOKEN_INT, r"-?\d+(?:e[+\-]?\d+)?\b"),
(TOKEN_INT, r"-?\d+(?P<G_EXP>e[+\-]?\d+)?\b"),
(TOKEN_DDOT, r"\.\."),
(TOKEN_AND, self.bool_and_pattern),
(TOKEN_OR, self.bool_or_pattern),
Expand Down Expand Up @@ -265,6 +265,19 @@ def tokenize(self, path: str) -> Iterator[Token]: # noqa PLR0912
value=match.group("G_SQUOTE"),
index=match.start("G_SQUOTE"),
)
elif kind == TOKEN_INT:
if match.group("G_EXP") and match.group("G_EXP")[1] == "-":
yield _token(
kind=TOKEN_FLOAT,
value=match.group(),
index=match.start(),
)
else:
yield _token(
kind=TOKEN_INT,
value=match.group(),
index=match.start(),
)
elif kind == TOKEN_RE_PATTERN:
yield _token(
kind=TOKEN_RE_PATTERN,
Expand Down
3 changes: 2 additions & 1 deletion jsonpath/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,8 @@ def parse_string_literal(self, stream: TokenStream) -> FilterExpression:
return StringLiteral(value=self._decode_string_literal(stream.current))

def parse_integer_literal(self, stream: TokenStream) -> FilterExpression:
return IntegerLiteral(value=int(stream.current.value))
# Convert to float first to handle scientific notation.
return IntegerLiteral(value=int(float(stream.current.value)))

def parse_float_literal(self, stream: TokenStream) -> FilterExpression:
return FloatLiteral(value=float(stream.current.value))
Expand Down
3 changes: 0 additions & 3 deletions tests/test_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ class Case:
"filter, multiple selectors, filter and wildcard": "TODO",
"filter, multiple selectors, filter and slice": "TODO",
"filter, multiple selectors, comparison filter, index and slice": "TODO",
"filter, equals number, exponent": "TODO",
"filter, equals number, positive exponent": "TODO",
"filter, equals number, negative exponent": "TODO",
"filter, equals number, decimal fraction, no fractional digit": "TODO",
"functions, length, result must be compared": "ignore",
"functions, count, result must be compared": "ignore",
Expand Down

0 comments on commit f2bc762

Please sign in to comment.