def test_expand_refs_empty_input(): # Shouldn't raise an exception, nothing else to check. Parser.expand_refs(ID_BASE, None) input_ = {} Parser.expand_refs(ID_BASE, input_) assert input_ == {}
def test_set_context(parser): other_name = 'different_from_any_name' p = Parser(INPUT_DICT, ANY_NAME) p.mark_object = mock.Mock() p.set_context(other_name, ANY_OBJ) assert p.name == other_name assert p.obj is ANY_OBJ assert p.mark_object.called_once_with(ANY_OBJ)
def find(self, reference): """ Resolve a reference using this servicedef as a relative base Returns a jsonschema.Schema instance :param reference: string reference to resolve The `reference` may be one of three supported forms: * `<server><path>#<fragment>` - fully qualified reference * `<path>#<fragment>` - reference is resolved against the same <server> as `servicedef`. <path> starts with '/' * `#<fragment>` - reference is resolved against the same <server> and <path> as `servicedef` :raises InvalidReference: `reference` does not appear to be to the correct syntax """ parsed_reference = urlparse.urlparse(reference) if parsed_reference.netloc or parsed_reference.path: # More than just a fragment, expand the id and find the full # servicedef by id full_reference = Parser.expand_ref(self.id, reference) reference_id = urlparse.urldefrag(full_reference)[0] if reference_id == self.id: servicedef = self else: if self.manager is None: raise NoManager(reference) servicedef = self.manager.find_by_id(reference_id) else: servicedef = self # Now that we have a servicedef, look to the fragment for: # '/resource/<resource_name>/...' # '/types/<type_name>/... p = JsonPointer(parsed_reference.fragment) if p.parts[0] == "resources": schema = servicedef.find_resource(p.parts[1]) elif p.parts[0] == "types": schema = servicedef.find_type(p.parts[1]) else: raise InvalidReference("Expected '/resources' or '/types'", reference) if len(p.parts) > 2 and schema is not None: return schema.by_pointer("/" + "/".join(p.parts[2:])) else: return schema
def _eval_shallow(servicedef, obj, need_copy=False): """Resolve $ref and $merge in obj, using servicedef for remote references. This function takes an input object which is a dictionary, and evaluates $merge / $ref only if they are present at the root of the object. If need_copy is True, a modifyable shallow copy is returned. """ # _eval_shallow() resolves $ref and $merge to their values in # source and with_. This is a *shallow* evaluation in that embedded # $ref or $merge at deeper levels are *not* resolved. # # For example, the following will be resolved: # { $ref: ... } # { $merge: ... } # # But the following will *not* be resolved # { type: object, # properties: { x: { $ref: ... } } } # # Need to loop in the event that a $ref resolves to another $ref # or a $ref to a $merge: # # { $ref: <target1> } --> { $ref: <target2> } --> { <value2> } # # Minimize copies so that we don't bloat memory done = False is_copy = False while not done: if '$merge' in obj: with Parser(obj['$merge'], 'eval_shallow') as merge_parser: merge_source = merge_parser.parse('source', save=False, required=True) merge_with = merge_parser.parse('with', save=False, required=True) # This always returns a copy obj = json_merge_patch(servicedef, merge_source, merge_with) is_copy = True elif '$ref' in obj: if len(list(obj.keys())) != 1: raise ParseError( "$ref object may not have any other properties", obj) sch = servicedef.find(obj['$ref']) obj = sch.input is_copy = False else: done = True if not is_copy and need_copy: obj = copy.copy(obj) return obj
def test_preprocess(): with mock.patch('reschema.parser.Parser.expand_refs'): Parser.preprocess(ID_BASE, copy.deepcopy(INPUT_LIST)) Parser.expand_refs.assert_called_once_with(ID_BASE, INPUT_LIST)
def test_expanded_refs_array(): # This ends up covering the dict case as well, since the $ref must # be a dict itself. input_ = copy.deepcopy(INPUT_LIST) Parser.expand_refs(ID_BASE, input_) assert input_ == INPUT_LIST_EXPANDED
def test_full_ref(): id_ = '%s%s' % (ID_HOSTNAME, ID_ABSPATH_FRAGMENT) assert Parser.expand_ref(ID_BASE, id_) == id_
def test_provider_ref(): expanded = Parser.expand_ref(ID_BASE, ID_ABSPATH_FRAGMENT) assert expanded == '%s%s' % (ID_HOSTNAME, ID_ABSPATH_FRAGMENT)
def test_local_ref(): assert Parser.expand_ref( ID_BASE, ID_FRAGMENT) == '%s%s' % (ID_BASE, ID_FRAGMENT)