def test_anchoring_markers(self): tests = { '@.a': ((c.ANCHOR_LOCAL | c.TYPE_DICT | c.KEY_LITERAL, 'a'), ), '$.a': ((c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'), ), '@[0]': ((c.ANCHOR_LOCAL | c.TYPE_LIST | c.KEY_LITERAL, 0), ), '$[0]': ((c.ANCHOR_ROOT | c.TYPE_LIST | c.KEY_LITERAL, 0), ), ':0': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_LIST | c.KEY_LITERAL, 0), ), '.a': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'), ), 'a': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'), ), '$..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_ROOT, '*'), ), '@..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_LOCAL, '*'), ), '..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_LOCAL | c.ANCHOR_ROOT, '*'), ), } for path_string, expected_parts in tests.iteritems(): self._compare_paths(path_string, parse_path(path_string), expected_parts)
def apply_map(self, path_string, function): def _map(terminal, parent, key, **kwargs): if terminal: parent[key] = function(parent=parent, key=key, **kwargs) walk_path(self, _map, parse_path(path_string)) return self
def test_canonical_path(self): paths = json_fixture('format/canonical_paths.json') for string_path, expected in paths.iteritems(): self.assertEqual( canonical_path(parse_path(string_path)), expected, "Converted '%s' to '%s'" % (string_path, expected)) with self.assertRaises(Exception): canonical_path((c.KEY_WILD | c.TYPE_LIST, '*'))
def test_parser(self): tests = { # Dict keys '9': ((c.KEY_LITERAL | c.TYPE_DICT, '9'),), 'a': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'),), '.a': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'),), '["a"]': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'),), "['a']": ((c.KEY_LITERAL | c.TYPE_DICT, 'a'),), "['a', 'b']": ((c.KEY_SLICE | c.TYPE_DICT, ('a', 'b')),), '*': ((c.KEY_WILD | c.TYPE_DICT, '*'),), '.*': ((c.KEY_WILD | c.TYPE_DICT, '*'),), '[*]': ((c.KEY_WILD | c.TYPE_DICT, '*'),), '["a", "b"]': ((c.KEY_SLICE | c.TYPE_DICT, ('a', 'b')),), # List indices ':*': ((c.KEY_WILD | c.TYPE_LIST, '*'),), ':0': [(c.TYPE_LIST | c.KEY_LITERAL, 0), ], '[0]': [(c.TYPE_LIST | c.KEY_LITERAL, 0), ], ':-1': [(c.TYPE_LIST | c.KEY_LITERAL, -1), ], '[-1]': [(c.TYPE_LIST | c.KEY_LITERAL, -1), ], '[:]': [(c.TYPE_LIST | c.KEY_SLICE, slice(None, None, None)), ], '[::]': [(c.TYPE_LIST | c.KEY_SLICE, slice(None, None, None)), ], '[0:]': [(c.TYPE_LIST | c.KEY_SLICE, slice(0, None, None)), ], '[:0]': [(c.TYPE_LIST | c.KEY_SLICE, slice(None, 0, None)), ], '[::0]': [(c.TYPE_LIST | c.KEY_SLICE, slice(None, None, 0)), ], ':0:0': [ (c.TYPE_LIST | c.KEY_LITERAL, 0), (c.TYPE_LIST | c.KEY_LITERAL, 0) ], ':0,1,2': [(c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], '[0,1,2]': [(c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], ':0, 1, 2': [(c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], '[0, 1, 2]': [(c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], # Recursing '..a': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, 'a'),), '..*': ((c.TRAVERSAL_RECURSE | c.KEY_WILD | c.TYPE_DICT, '*'),), '..[9]': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_LIST, 9),), '..9': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, '9'),), '..:9': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_LIST, 9),), '..["a"]': ( (c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, 'a'),), '..[*]': ((c.TRAVERSAL_RECURSE | c.KEY_WILD | c.TYPE_DICT, '*'),), } for path_string, expected_parts in tests.iteritems(): got_parts = parse_path(path_string) # Strip out the anchoring markers we don't care about root = got_parts[0] got_parts[0] = (root[0] ^ (c.ANCHOR_ROOT | c.ANCHOR_LOCAL), root[1]) self._compare_paths(path_string, got_parts, expected_parts)
def __getitem__(self, item): if isinstance(item, list): path_parts = parse_path(item[0]) for key_type, _ in path_parts: if key_type & (c.KEY_WILD | c.KEY_SLICE | c.TRAVERSAL_RECURSE): return crud.find_path_parts(self, path_parts) default = None if len(item) > 1: default = item[1] return crud.get_path_parts(self, path_parts, default=default) return super(DataPathDict, self).__getitem__(item)
def test_parser_splitting(self): tests = { 'a.b': ['a', 'b'], 'a[6]': ['a', 6], 'a\\.b': ['a.b'], 'a\\.b.c': ['a.b', 'c'], '["["]': ['['], 'a.*': ['a', '*'], 'a[*]': ['a', '*'], 'a..b': ['a', 'b'], '\\[\\]': ['[]'], '["[]"]': ['[]'] } for path_string, keys in tests.iteritems(): got_keys = [key for _, key in parse_path(path_string)] self.assertEqual(got_keys, keys, "Correctly get the parts for '%s'" % path_string)
def test_parser_typing(self): tests = { 'a': ('a', c.TYPE_DICT | c.KEY_LITERAL), '.a': ('a', c.TYPE_DICT | c.KEY_LITERAL), '["a"]': ('a', c.TYPE_DICT | c.KEY_LITERAL), "['a']": ('a', c.TYPE_DICT | c.KEY_LITERAL), '[1]': (1, c.TYPE_LIST | c.KEY_LITERAL), '*': ('*', c.KEY_WILD | c.TYPE_DICT | c.TYPE_LIST), '.*': ('*', c.KEY_WILD | c.TYPE_DICT | c.TYPE_LIST), '[*]': ('*', c.KEY_WILD | c.TYPE_DICT | c.TYPE_LIST), '..a': ('a', c.KEY_RECURSE | c.KEY_LITERAL | c.TYPE_DICT), } for path, (key, key_type) in tests.iteritems(): path_parts = parse_path(path) got_type, got_key = path_parts[0] self.assertEqual(len(path_parts), 1, 'Got one part for %s' % path) self.assertEqual(got_key, key, 'Got the expected key for %s' % path) self.assertEqual(got_type, key_type, 'Got the expected type for %s' % path)
def test_anchoring_markers(self): tests = { '@.a': ((c.ANCHOR_LOCAL | c.TYPE_DICT | c.KEY_LITERAL, 'a'),), '$.a': ((c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'),), '@[0]': ((c.ANCHOR_LOCAL | c.TYPE_LIST | c.KEY_LITERAL, 0),), '$[0]': ((c.ANCHOR_ROOT | c.TYPE_LIST | c.KEY_LITERAL, 0),), ':0': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_LIST | c.KEY_LITERAL, 0),), '.a': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'),), 'a': ((c.ANCHOR_LOCAL | c.ANCHOR_ROOT | c.TYPE_DICT | c.KEY_LITERAL, 'a'),), '$..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_ROOT, '*'),), '@..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_LOCAL, '*'),), '..*': ((c.TYPE_DICT | c.KEY_WILD | c.TRAVERSAL_RECURSE | c.ANCHOR_LOCAL | c.ANCHOR_ROOT, '*'),), } for path_string, expected_parts in tests.iteritems(): self._compare_paths( path_string, parse_path(path_string), expected_parts)
def set_path(data, path_string, value, copy=False): return set_path_parts(data, parse_path(path_string), value, copy)
def find_path(data, path_string, on_mismatch=c.ON_MISMATCH_CONTINUE): return find_path_parts(data, parse_path(path_string), on_mismatch)
def get_path(data, path_string, default=None): return get_path_parts(data, parse_path(path_string), default)
def apply(self, path_string, function): walk_path(self, function, parse_path(path_string)) return self
def set_path(data, path_string, value): return set_path_parts(data, parse_path(path_string), value)
def test_compact_path(self): paths = json_fixture('format/compact_paths.json') for string_path, expected in paths.iteritems(): self.assertEqual( compact_path(parse_path(string_path)), expected, "Converted '%s' to '%s'" % (string_path, expected))
def __init__(self, path_string): self.path_string = path_string self.parts = parse_path(path_string)
def test_parser(self): tests = { # Dict keys '9': ((c.KEY_LITERAL | c.TYPE_DICT, '9'), ), 'a': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), '.a': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), '["a"]': ((c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), "['a']": ((c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), "['a', 'b']": ((c.KEY_SLICE | c.TYPE_DICT, ('a', 'b')), ), '*': ((c.KEY_WILD | c.TYPE_DICT, '*'), ), '.*': ((c.KEY_WILD | c.TYPE_DICT, '*'), ), '[*]': ((c.KEY_WILD | c.TYPE_DICT, '*'), ), '["a", "b"]': ((c.KEY_SLICE | c.TYPE_DICT, ('a', 'b')), ), # List indices ':*': ((c.KEY_WILD | c.TYPE_LIST, '*'), ), ':0': [ (c.TYPE_LIST | c.KEY_LITERAL, 0), ], '[0]': [ (c.TYPE_LIST | c.KEY_LITERAL, 0), ], ':-1': [ (c.TYPE_LIST | c.KEY_LITERAL, -1), ], '[-1]': [ (c.TYPE_LIST | c.KEY_LITERAL, -1), ], '[:]': [ (c.TYPE_LIST | c.KEY_SLICE, slice(None, None, None)), ], '[::]': [ (c.TYPE_LIST | c.KEY_SLICE, slice(None, None, None)), ], '[0:]': [ (c.TYPE_LIST | c.KEY_SLICE, slice(0, None, None)), ], '[:0]': [ (c.TYPE_LIST | c.KEY_SLICE, slice(None, 0, None)), ], '[::0]': [ (c.TYPE_LIST | c.KEY_SLICE, slice(None, None, 0)), ], ':0:0': [(c.TYPE_LIST | c.KEY_LITERAL, 0), (c.TYPE_LIST | c.KEY_LITERAL, 0)], ':0,1,2': [ (c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], '[0,1,2]': [ (c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], ':0, 1, 2': [ (c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], '[0, 1, 2]': [ (c.TYPE_LIST | c.KEY_SLICE, (0, 1, 2)), ], # Recursing '..a': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), '..*': ((c.TRAVERSAL_RECURSE | c.KEY_WILD | c.TYPE_DICT, '*'), ), '..[9]': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_LIST, 9), ), '..9': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, '9'), ), '..:9': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_LIST, 9), ), '..["a"]': ((c.TRAVERSAL_RECURSE | c.KEY_LITERAL | c.TYPE_DICT, 'a'), ), '..[*]': ((c.TRAVERSAL_RECURSE | c.KEY_WILD | c.TYPE_DICT, '*'), ), } for path_string, expected_parts in tests.iteritems(): got_parts = parse_path(path_string) # Strip out the anchoring markers we don't care about root = got_parts[0] got_parts[0] = (root[0] ^ (c.ANCHOR_ROOT | c.ANCHOR_LOCAL), root[1]) self._compare_paths(path_string, got_parts, expected_parts)