Skip to content

Commit

Permalink
refactor: finish operator: wildcard & recursive descent
Browse files Browse the repository at this point in the history
  • Loading branch information
sean2077 committed Dec 31, 2020
1 parent 1092628 commit a188803
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ uninstall:
pip uninstall jsonpath

test:
pytest tests -vv -s
pytest test -vv -s

clean:
rm -rf $(PYCACHE_DIR) ${PYTEST_DIR}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ A more powerful JSONPath implementations in modern python.
- [ ] Powerful filtering function, including multi-selection, inverse-selection filtering.
- [ ] Powerful sorting function, including sorting by multiple fields, ascending and descending order.

## Issues

- Not support parent operator.

## Examples

JSON format data:
Expand Down
56 changes: 29 additions & 27 deletions jsonpath/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Author : zhangxianbing1
Date : 2020-12-27 09:22:14
LastEditors : zhangxianbing1
LastEditTime : 2020-12-30 17:39:37
LastEditTime : 2020-12-31 11:07:08
Description : JSONPath
"""
__version__ = "1.0.0"
Expand Down Expand Up @@ -65,10 +65,11 @@ def __init__(self, expr: str, *, result_type="VALUE"):
expr = self._parse_expr(expr)
self.ops = expr.split(SEP)
self.oplen = len(self.ops)
print(f"operations : {self.ops}")

def _parse_expr(self, expr):
if __debug__:
print(f"before expr: {expr}")
print(f"before expr : {expr}")

expr = REP_PICKUP_QUOTE.sub(self._f_pickup_quote, expr)
expr = REP_PICKUP_BRACKET.sub(self._f_pickup_bracket, expr)
Expand All @@ -80,7 +81,7 @@ def _parse_expr(self, expr):
expr = expr[2:]

if __debug__:
print(f"after expr: {expr}")
print(f"after expr : {expr}")
return expr

def _f_pickup_quote(self, m):
Expand Down Expand Up @@ -108,7 +109,7 @@ def parse(self, obj):
else:
self.result = []

self._trace(obj, 0)
self._operate(obj, 0)

return self.result

Expand All @@ -117,47 +118,48 @@ def _op(self, i):
return self.ops[i]
return None

def _trace(self, obj, idx, op=None):
# obj - 当前处理对象
# idx - 当前操作在操作集中的序号
# op - 覆盖idx指定操作的操作
def _traverse(self, f, obj, idx: int):
if isinstance(obj, list):
for i, v in enumerate(obj):
f(v, idx)
elif isinstance(obj, dict):
for k, v in obj.items():
f(v, idx)

def _operate(self, obj, idx: int):
"""Perform operation on object.
Args:
obj ([type]): current operating object
idx (int): current operation specified by index in self.ops
"""

# store
if idx >= self.oplen:
self.result.append(obj)
print(obj)
return

op = op or self.ops[idx]
op = self.ops[idx]

# getall
# wildcard
if op == "*":
if isinstance(obj, list):
for i, v in enumerate(obj):
self._trace(v, idx + 1)
elif isinstance(obj, dict):
for k, v in obj.items():
self._trace(v, idx + 1)

# traverse
self._traverse(self._operate, obj, idx + 1)

# recursive descent
elif op == "..":
self._trace(obj, idx + 1)
if isinstance(obj, list):
for i, v in enumerate(obj):
self._trace(v, idx + 1, "..")
elif isinstance(obj, dict):
for k, v in obj.items():
self._trace(v, idx + 1, "..")
self._operate(obj, idx + 1)
self._traverse(self._operate, obj, idx)

# get value from dict
elif isinstance(obj, dict) and op in obj:
self._trace(obj[op], idx + 1)
self._operate(obj[op], idx + 1)

# get value from list
elif isinstance(obj, list) and op.isdigit():
ikey = int(op)
if ikey < len(obj):
self._trace(obj[ikey], idx + 1)
self._operate(obj[ikey], idx + 1)

# elif key.startswith("?(") and key.endswith(")"): # filter
# pass
Expand Down
3 changes: 3 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"bicycle": {"color": "red", "price": 19.95},
}

prices = [8.95, 12.99, 8.99, 22.99, 19.95]


@pytest.fixture(
params=[
Expand All @@ -44,6 +46,7 @@
TestCase("$[book]", data, [data["book"]]),
TestCase("$.'a.b c'", data, [data["a.b c"]]),
TestCase("$['a.b c']", data, [data["a.b c"]]),
TestCase("$..price", data, prices),
]
)
def cases(request):
Expand Down

0 comments on commit a188803

Please sign in to comment.