Skip to content

Commit 705bc3e

Browse files
committed
add include function
1 parent cd6e5e0 commit 705bc3e

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

jsonpath_rw/jsonpath.py

+43
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,11 @@ def exclude(self, data):
267267
self.right.exclude(datum.value)
268268
return data
269269

270+
def include(self, data):
271+
for datum in self.left.find(data):
272+
self.right.include(datum.value)
273+
return data
274+
270275
def __eq__(self, other):
271276
return isinstance(other, Child) and self.left == other.left and self.right == other.right
272277

@@ -524,6 +529,23 @@ def exclude(self, data):
524529
del data[field]
525530
return data
526531

532+
def include(self, data):
533+
datum = DatumInContext.wrap(data)
534+
535+
try:
536+
all_fields = tuple(datum.value.keys())
537+
except AttributeError:
538+
all_fields = ()
539+
540+
path_fields = self.reified_fields(datum)
541+
remove_fields = set(all_fields) - set(path_fields)
542+
543+
for field in remove_fields:
544+
if field in data:
545+
del data[field]
546+
547+
return data
548+
527549
def __str__(self):
528550
return ','.join(map(str, self.fields))
529551

@@ -564,6 +586,15 @@ def exclude(self, data):
564586
del data[self.index]
565587
return data
566588

589+
def include(self, data):
590+
if data is None:
591+
return None
592+
593+
if len(data) > self.index:
594+
return [data[self.index]]
595+
596+
return []
597+
567598
def __eq__(self, other):
568599
return isinstance(other, Index) and self.index == other.index
569600

@@ -625,6 +656,18 @@ def exclude(self, data):
625656

626657
return data
627658

659+
def include(self, data):
660+
661+
if not data:
662+
return data
663+
664+
ret = []
665+
for datum in self.find(data):
666+
ret.append(datum.value)
667+
668+
data = ret
669+
return data
670+
628671
def __str__(self):
629672
if self.start == None and self.end == None and self.step == None:
630673
return '[*]'

tests/test_jsonpath.py

+81-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,87 @@ def test_exclude_slice(self):
463463

464464
def check_include_cases(self, test_cases):
465465
for original, string, expected in test_cases:
466-
logging.debug('parse("%s").exclude(%s) =?= %s' % (string, original, expected))
466+
logging.debug('parse("%s").include(%s) =?= %s' % (string, original, expected))
467467
actual = parse(string).include(original)
468468
assert actual == expected
469469

470+
def test_include_fields(self):
471+
self.check_include_cases([
472+
({'foo': 'baz'}, 'foo', {'foo': 'baz'}),
473+
({'foo': 1, 'baz': 2}, 'foo', {'foo': 1}),
474+
({'foo': 1, 'baz': 2}, 'foo,baz', {'foo': 1, 'baz': 2}),
475+
({'@foo': 1}, '@foo', {'@foo': 1}),
476+
({'@foo': 1, 'baz': 2}, '@foo', {'@foo': 1}),
477+
({'foo': 1, 'baz': 2}, '*', {'foo': 1, 'baz': 2}),
478+
])
479+
480+
def test_include_index(self):
481+
self.check_include_cases([
482+
([42], '[0]', [42]),
483+
([42], '[5]', []),
484+
([34, 65, 29, 59], '[2]', [29]),
485+
(None, '[0]', None),
486+
([], '[0]', []),
487+
(['foo', 'bar', 'baz'], '[0]', ['foo']),
488+
])
489+
490+
def test_include_slice(self):
491+
self.check_include_cases([
492+
(['foo', 'bar', 'baz'], '[0:2]', ['foo', 'bar']),
493+
(['foo', 'bar', 'baz'], '[0:1]', ['foo']),
494+
(['foo', 'bar', 'baz'], '[0:]', ['foo', 'bar', 'baz']),
495+
(['foo', 'bar', 'baz'], '[:2]', ['foo', 'bar']),
496+
(['foo', 'bar', 'baz'], '[:3]', ['foo', 'bar', 'baz']),
497+
(['foo', 'bar', 'baz'], '[0:0]', []),
498+
])
499+
500+
def test_include_root(self):
501+
self.check_include_cases([
502+
('foo', '$', 'foo'),
503+
({}, '$', {}),
504+
({'foo': 1}, '$', {'foo': 1})
505+
])
506+
507+
def test_include_this(self):
508+
self.check_include_cases([
509+
('foo', '`this`', 'foo'),
510+
({}, '`this`', {}),
511+
({'foo': 1}, '`this`', {'foo': 1}),
512+
# TODO: fixme
513+
#({'foo': 1}, 'foo.`this`', {}),
514+
({'foo': {'bar': 1}}, 'foo.`this`.bar', {'foo': {'bar': 1}}),
515+
({'foo': {'bar': 1, 'baz': 2}}, 'foo.`this`.bar', {'foo': {'bar': 1}})
516+
])
517+
518+
def test_include_child(self):
519+
self.check_include_cases([
520+
({'foo': 'bar'}, '$.foo', {'foo': 'bar'}),
521+
({'foo': 'bar'}, 'foo', {'foo': 'bar'}),
522+
({'foo': {'bar': 1}}, 'foo.bar', {'foo': {'bar': 1}}),
523+
({'foo': {'bar': 1}}, 'foo.$.foo.bar', {'foo': {'bar': 1}}),
524+
({'foo': {'bar': 1, 'baz': 2}}, 'foo.$.foo.bar', {'foo': {'bar': 1}}),
525+
({'foo': {'bar': 1, 'baz': 2}}, '*', {'foo': {'bar': 1, 'baz': 2}}),
526+
({'foo': {'bar': 1, 'baz': 2}}, 'non', {}),
527+
])
528+
529+
"""
530+
def test_include_where(self):
531+
self.check_include_cases([
532+
#({'foo': {'bar': {'baz': 1}}, 'bar': {'baz': 2}},
533+
# '*.bar where none', {}),
534+
535+
({'foo': {'bar': {'baz': 1}}, 'bar': {'baz': 2}},
536+
'*.bar where baz', {'foo': {'bar': {'baz': 1}}})
537+
])
538+
"""
539+
540+
"""
541+
def test_include_descendants(self):
542+
self.check_include_cases([
543+
({'somefield': 1}, '$..somefield', {'somefield': 1}),
544+
({'outer': {'nestedfield': 1}}, '$..nestedfield', {'outer': {'nestedfield': 1}}),
545+
({'outs': {'bar': 1, 'ins': {'bar': 9}}, 'outs2': {'bar': 2}},
546+
'$..bar',
547+
{'outs': {'bar': 1, 'ins': {'bar': 9}}, 'outs2': {'bar': 2}})
548+
])
549+
"""

0 commit comments

Comments
 (0)