|
1 | 1 | from __future__ import unicode_literals, print_function, absolute_import, division, generators, nested_scopes
|
2 | 2 | import logging
|
| 3 | +from operator import gt |
3 | 4 | import six
|
4 | 5 | from six.moves import xrange
|
5 | 6 | from itertools import *
|
@@ -565,3 +566,40 @@ def __repr__(self):
|
565 | 566 |
|
566 | 567 | def __eq__(self, other):
|
567 | 568 | return isinstance(other, Slice) and other.start == self.start and self.end == other.end and other.step == self.step
|
| 569 | + |
| 570 | + |
| 571 | +class Cmp(JSONPath): |
| 572 | + """ |
| 573 | + A JSONPath expression that supports value comparison |
| 574 | +
|
| 575 | + >>> jsonpath_expr = Cmp(Child(Slice(), Fields('spam')), gt, 2) # "[*].spam gt 2" |
| 576 | + >>> matches = jsonpath_expr.find([ |
| 577 | + ... {"spam": 2, "bacon": 1, "sausage": 1}, |
| 578 | + ... {"spam": 10, "baked beans": 1} |
| 579 | + ... ]) |
| 580 | + >>> [match.value for match in matches] |
| 581 | + [10] |
| 582 | +
|
| 583 | + """ |
| 584 | + def __init__(self, jsonpath, operator, operand): |
| 585 | + if not hasattr(operator, '__call__'): |
| 586 | + raise ValueError('operator must be callable') |
| 587 | + self.jsonpath = jsonpath |
| 588 | + self.op = operator |
| 589 | + self.operand = operand |
| 590 | + |
| 591 | + def find(self, data): |
| 592 | + return [match for match in self.jsonpath.find(data) if self.op(match.value, self.operand)] |
| 593 | + |
| 594 | + def __str__(self): |
| 595 | + return '{jsonpath} {op} {operand}'.format( |
| 596 | + jsonpath=self.jsonpath, op=self.op.__name__, operand=repr(self.operand) |
| 597 | + ) |
| 598 | + |
| 599 | + def __eq__(self, other): |
| 600 | + return ( |
| 601 | + isinstance(other, Cmp) and |
| 602 | + other.jsonpath == self.jsonpath and |
| 603 | + other.op == self.op and |
| 604 | + other.operand == self.operand |
| 605 | + ) |
0 commit comments