Skip to content

Commit df9bdf1

Browse files
authored
Merge pull request #73 from jg-rp/issue72
Fix bare name selectors that start with a reserved word
2 parents 784c738 + a8e25c1 commit df9bdf1

File tree

7 files changed

+125
-14
lines changed

7 files changed

+125
-14
lines changed

.github/workflows/tests.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
fail-fast: false
1010
matrix:
11-
os: [ubuntu-latest, windows-latest, macos-latest]
11+
os: [ubuntu-22.04, windows-latest, macos-latest]
1212
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
1313
exclude:
1414
- os: macos-latest

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Python JSONPath Change Log
22

3+
## Version 1.2.2 (unreleased)
4+
5+
**Fixes**
6+
7+
- Fixed parsing of bare name selectors that start with a reserved word. See [issue #72](https://github.com/jg-rp/python-jsonpath/issues/72).
8+
39
## Version 1.2.1
410

511
**Fixes**

docs/syntax.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ $.categories[0][name]
4242
$.categories[0]['name']
4343
```
4444

45+
By default, `or`, `and`, `in`, `true`, `True`, `false`, `False`, `nil`, `Nil`, `null`, `Null`, `none`, `None`, `contains`, `undefined`, and `missing` are considered _reserved words_. In some cases you will need to use quoted property/name selector syntax if you're selecting a name that matches any of these words exactly. For example, `["and"]`.
46+
4547
### Array indices (`[0]` or `[-1]`)
4648

4749
Select an item from an array by its index. Indices are zero-based and enclosed in brackets. If the index is negative, items are selected from the end of the array. Considering example data from the top of this page, the following examples are equivalent.

jsonpath/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2023-present James Prior <jamesgr.prior@gmail.com>
22
#
33
# SPDX-License-Identifier: MIT
4-
__version__ = "1.2.1"
4+
__version__ = "1.2.2"

jsonpath/lex.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ class attributes. Then setting `lexer_class` on a `JSONPathEnvironment`.
8888
key_pattern = r"[\u0080-\uFFFFa-zA-Z_][\u0080-\uFFFFa-zA-Z0-9_-]*"
8989

9090
# `not` or !
91-
logical_not_pattern = r"(?:not|!)"
91+
logical_not_pattern = r"(?:not\b)|!"
9292

9393
# && or `and`
94-
logical_and_pattern = r"(?:&&|and)"
94+
logical_and_pattern = r"&&|(?:and\b)"
9595

9696
# || or `or`
97-
logical_or_pattern = r"(?:\|\||or)"
97+
logical_or_pattern = r"\|\||(?:or\b)"
9898

9999
def __init__(self, *, env: JSONPathEnvironment) -> None:
100100
self.env = env
@@ -153,15 +153,15 @@ def compile_rules(self) -> Pattern[str]:
153153
],
154154
(TOKEN_WILD, r"\*"),
155155
(TOKEN_FILTER, r"\?"),
156-
(TOKEN_IN, r"in"),
157-
(TOKEN_TRUE, r"[Tt]rue"),
158-
(TOKEN_FALSE, r"[Ff]alse"),
159-
(TOKEN_NIL, r"[Nn]il"),
160-
(TOKEN_NULL, r"[Nn]ull"),
161-
(TOKEN_NONE, r"[Nn]one"),
162-
(TOKEN_CONTAINS, r"contains"),
163-
(TOKEN_UNDEFINED, r"undefined"),
164-
(TOKEN_MISSING, r"missing"),
156+
(TOKEN_IN, r"in\b"),
157+
(TOKEN_TRUE, r"[Tt]rue\b"),
158+
(TOKEN_FALSE, r"[Ff]alse\b"),
159+
(TOKEN_NIL, r"[Nn]il\b"),
160+
(TOKEN_NULL, r"[Nn]ull\b"),
161+
(TOKEN_NONE, r"[Nn]one\b"),
162+
(TOKEN_CONTAINS, r"contains\b"),
163+
(TOKEN_UNDEFINED, r"undefined\b"),
164+
(TOKEN_MISSING, r"missing\b"),
165165
(TOKEN_LIST_START, r"\["),
166166
(TOKEN_RBRACKET, r"]"),
167167
(TOKEN_COMMA, r","),

tests/test_find.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,30 @@ class Case:
127127
}
128128
],
129129
),
130+
Case(
131+
description="issue 72, orders",
132+
path="orders",
133+
data={"orders": [1, 2, 3]},
134+
want=[[1, 2, 3]],
135+
),
136+
Case(
137+
description="issue 72, andy",
138+
path="andy",
139+
data={"andy": [1, 2, 3]},
140+
want=[[1, 2, 3]],
141+
),
142+
Case(
143+
description="quoted reserved word, and",
144+
path="['and']",
145+
data={"and": [1, 2, 3]},
146+
want=[[1, 2, 3]],
147+
),
148+
Case(
149+
description="quoted reserved word, or",
150+
path="['or']",
151+
data={"or": [1, 2, 3]},
152+
want=[[1, 2, 3]],
153+
),
130154
]
131155

132156

tests/test_lex.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,6 +1375,85 @@ class Case:
13751375
Token(kind=TOKEN_RBRACKET, value="]", index=9, path="$.thing[~]"),
13761376
],
13771377
),
1378+
Case(
1379+
description="implicit root selector, name selector starts with `and`",
1380+
path="anderson",
1381+
want=[
1382+
Token(kind=TOKEN_BARE_PROPERTY, value="anderson", index=0, path="anderson"),
1383+
],
1384+
),
1385+
Case(
1386+
description="implicit root selector, name selector starts with `or`",
1387+
path="order",
1388+
want=[
1389+
Token(kind=TOKEN_BARE_PROPERTY, value="order", index=0, path="order"),
1390+
],
1391+
),
1392+
Case(
1393+
description="implicit root selector, name selector starts with `true`",
1394+
path="trueblue",
1395+
want=[
1396+
Token(kind=TOKEN_BARE_PROPERTY, value="trueblue", index=0, path="trueblue"),
1397+
],
1398+
),
1399+
Case(
1400+
description="implicit root selector, name selector starts with `false`",
1401+
path="falsehood",
1402+
want=[
1403+
Token(
1404+
kind=TOKEN_BARE_PROPERTY, value="falsehood", index=0, path="falsehood"
1405+
),
1406+
],
1407+
),
1408+
Case(
1409+
description="implicit root selector, name selector starts with `not`",
1410+
path="nottingham",
1411+
want=[
1412+
Token(
1413+
kind=TOKEN_BARE_PROPERTY, value="nottingham", index=0, path="nottingham"
1414+
),
1415+
],
1416+
),
1417+
Case(
1418+
description="implicit root selector, name selector starts with `null`",
1419+
path="nullable",
1420+
want=[
1421+
Token(kind=TOKEN_BARE_PROPERTY, value="nullable", index=0, path="nullable"),
1422+
],
1423+
),
1424+
Case(
1425+
description="implicit root selector, name selector starts with `none`",
1426+
path="nonexpert",
1427+
want=[
1428+
Token(
1429+
kind=TOKEN_BARE_PROPERTY, value="nonexpert", index=0, path="nonexpert"
1430+
),
1431+
],
1432+
),
1433+
Case(
1434+
description="implicit root selector, name selector starts with `undefined`",
1435+
path="undefinedness",
1436+
want=[
1437+
Token(
1438+
kind=TOKEN_BARE_PROPERTY,
1439+
value="undefinedness",
1440+
index=0,
1441+
path="undefinedness",
1442+
),
1443+
],
1444+
),
1445+
Case(
1446+
description="implicit root selector, name selector starts with `missing`",
1447+
path="missingly",
1448+
want=[
1449+
Token(
1450+
kind=TOKEN_BARE_PROPERTY,
1451+
value="missingly",
1452+
index=0,
1453+
path="missingly",
1454+
),
1455+
],
1456+
),
13781457
]
13791458

13801459

0 commit comments

Comments
 (0)