def format_validation_error(err: ValidationError, instance_name=None, schema_name=None): instance_path = JsonPointer.from_parts(err.absolute_path).path schema_path = JsonPointer.from_parts(err.absolute_schema_path).path return f'''\
def compare_dicts(path, src, dst): for key in src: if key not in dst: ptr = JsonPointer.from_parts(path + [key]) yield {"op": "remove", "path": ptr.path} continue current = path + [key] for operation in compare_values(current, src[key], dst[key]): yield operation for key in dst: if key not in src: ptr = JsonPointer.from_parts(path + [key]) yield {"op": "add", "path": ptr.path, "value": dst[key]}
def compare_dicts(path, src, dst): for key in src: if key not in dst: ptr = JsonPointer.from_parts(path + [key]) yield {'op': 'remove', 'path': ptr.path} continue current = path + [key] for operation in compare_values(current, src[key], dst[key]): yield operation for key in dst: if key not in src: ptr = JsonPointer.from_parts(path + [key]) yield {'op': 'add', 'path': ptr.path, 'value': dst[key]}
def _compare_right(path, dst, right, shift): """Yields JSON patch ``add`` operations for elements that are only exists in the `dst` list""" start, end = right if end == -1: end = len(dst) for idx in range(start, end): ptr = JsonPointer.from_parts(path + [str(idx)]) yield ({'op': 'add', 'path': ptr.path, 'value': dst[idx]}, shift + 1) shift += 1
def _compare_right(path, dst, right, shift): """Yields JSON patch ``add`` operations for elements that are only exists in the `dst` list""" start, end = right if end == -1: end = len(dst) for idx in range(start, end): ptr = JsonPointer.from_parts(path + [str(idx)]) yield ({"op": "add", "path": ptr.path, "value": dst[idx]}, shift + 1) shift += 1
def _makeoffset(self, offset): ''' prepare a full offset based on this views' offset and a relative offset :param offset: the relative offset ''' thisoffset = JsonPointer(offset) if self.offset: fulloffset = JsonPointer.from_parts(JsonPointer(self.offset).parts + thisoffset.parts).path else: fulloffset = thisoffset.path return fulloffset
def compare_values(path, value, other): if value == other: return if isinstance(value, MutableMapping) and isinstance(other, MutableMapping): for operation in compare_dicts(path, value, other): yield operation elif isinstance(value, MutableSequence) and isinstance(other, MutableSequence): for operation in compare_lists(path, value, other): yield operation else: ptr = JsonPointer.from_parts(path) yield {"op": "replace", "path": ptr.path, "value": other}
def compare_values(path, value, other): if value == other: return if isinstance(value, dict) and isinstance(other, dict): for operation in compare_dicts(path, value, other): yield operation elif isinstance(value, list) and isinstance(other, list): for operation in compare_lists(path, value, other): yield operation else: ptr = JsonPointer.from_parts(path) yield {'op': 'replace', 'path': ptr.path, 'value': other}
def _makeoffset(self, offset): ''' prepare a full offset based on this views' offset and a relative offset :param offset: the relative offset ''' thisoffset = JsonPointer(offset) if self.offset: fulloffset = JsonPointer.from_parts( JsonPointer(self.offset).parts + thisoffset.parts).path else: fulloffset = thisoffset.path return fulloffset
def compare_values(path, value, other): if value == other: return if isinstance(value, MutableMapping) and \ isinstance(other, MutableMapping): for operation in compare_dicts(path, value, other): yield operation elif isinstance(value, MutableSequence) and \ isinstance(other, MutableSequence): for operation in compare_lists(path, value, other): yield operation else: ptr = JsonPointer.from_parts(path) yield {'op': 'replace', 'path': ptr.path, 'value': other}
def addWorkflow(self, rules, stage=None): ''' add a (sub-)workflow (i.e. list of stages) to the overall workflow ''' offset = '' if stage is not None: #make sure storage for the 'authoring' stage is present and #register the workflow as part of that 'author' #needed e.g. for predicate handlers trying to determing if #the author stage is done nextindex = len(self.steps.get(stage, [])) offset = JsonPointer.from_parts([stage, nextindex]).path self.steps.setdefault(stage, []).append({}) self.values.setdefault(stage, []).append({}) for rule in rules: self.addRule(rule, offset)
def addWorkflow(self, rules, stage=None): ''' add a (sub-)workflow (i.e. list of stages) to the overall workflow ''' offset = '' if stage is not None: #make sure storage for the 'authoring' stage is present and #register the workflow as part of that 'author' #needed e.g. for predicate handlers trying to determing if #the author stage is done nextindex = len(self.steps.get(stage,[])) offset = JsonPointer.from_parts([stage, nextindex]).path self.steps.setdefault(stage,[]).append({}) self.values.setdefault(stage,[]).append({}) for rule in rules: self.addRule(rule, offset)
def _compare_left(path, src, left, shift): """Yields JSON patch ``remove`` operations for elements that are only exists in the `src` list.""" start, end = left if end == -1: end = len(src) # we need to `remove` elements from list tail to not deal with index shift for idx in reversed(range(start + shift, end + shift)): ptr = JsonPointer.from_parts(path + [str(idx)]) yield ( {'op': 'remove', # yes, there should be any value field, but we'll use it # to apply `move` optimization a bit later and will remove # it in _optimize function. 'value': src[idx - shift], 'path': ptr.path, }, shift - 1 ) shift -= 1
def _compare_left(path, src, left, shift): """Yields JSON patch ``remove`` operations for elements that are only exists in the `src` list.""" start, end = left if end == -1: end = len(src) # we need to `remove` elements from list tail to not deal with index shift for idx in reversed(range(start + shift, end + shift)): ptr = JsonPointer.from_parts(path + [str(idx)]) yield ( { 'op': 'remove', # yes, there should be any value field, but we'll use it # to apply `move` optimization a bit later and will remove # it in _optimize function. 'value': src[idx - shift], 'path': ptr.path, }, shift - 1) shift -= 1
def test_round_trip(self): paths = [ "", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n", ] for path in paths: ptr = JsonPointer(path) self.assertEqual(path, ptr.path) parts = ptr.parts new_ptr = JsonPointer.from_parts(parts) self.assertEqual(ptr, new_ptr)
def test_round_trip(self): paths = [ "", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n", '/\xee', ] for path in paths: ptr = JsonPointer(path) self.assertEqual(path, ptr.path) parts = ptr.parts new_ptr = JsonPointer.from_parts(parts) self.assertEqual(ptr, new_ptr)
def create_path(self, tokens): return JsonPointer.from_parts(tokens).path