Example #1
0
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_ == {}
Example #2
0
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)
Example #3
0
    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
Example #4
0
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
Example #5
0
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)
Example #6
0
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
Example #7
0
def test_full_ref():
    id_ = '%s%s' % (ID_HOSTNAME, ID_ABSPATH_FRAGMENT)
    assert Parser.expand_ref(ID_BASE, id_) == id_
Example #8
0
def test_provider_ref():
    expanded = Parser.expand_ref(ID_BASE, ID_ABSPATH_FRAGMENT)
    assert expanded == '%s%s' % (ID_HOSTNAME, ID_ABSPATH_FRAGMENT)
Example #9
0
def test_local_ref():
    assert Parser.expand_ref(
        ID_BASE, ID_FRAGMENT) == '%s%s' % (ID_BASE, ID_FRAGMENT)