Exemplo n.º 1
0
    def create(name, item_constraint=None, **addl_constraints):
        """ Create an array validator based on the passed in constraints.

        If item_constraint is a tuple, it is assumed that tuple validation
        is being performed. If it is a class or dictionary, list validation
        will be performed. Classes are assumed to be subclasses of ProtocolBase,
        while dictionaries are expected to be basic types ('string', 'number', ...).

        addl_constraints is expected to be key-value pairs of any of the other
        constraints permitted by JSON Schema v4.
        """
        logger.debug(
            fmt("Constructing ArrayValidator with {} and {}", item_constraint,
                addl_constraints))
        from python_jsonschema_objects import classbuilder
        klassbuilder = addl_constraints.pop("classbuilder", None)
        props = {}

        if item_constraint is not None:
            if isinstance(item_constraint, (tuple, list)):
                for i, elem in enumerate(item_constraint):
                    isdict = isinstance(elem, (dict, ))
                    isklass = isinstance(elem, type) and util.safe_issubclass(
                        elem,
                        (classbuilder.ProtocolBase, classbuilder.LiteralValue))

                    if not any([isdict, isklass]):
                        raise TypeError(
                            "Item constraint (position {0}) is not a schema".
                            format(i))
            elif isinstance(item_constraint,
                            (classbuilder.TypeProxy, classbuilder.TypeRef)):
                pass
            elif util.safe_issubclass(item_constraint, ArrayWrapper):
                pass
            else:
                isdict = isinstance(item_constraint, (dict, ))
                isklass = isinstance(
                    item_constraint, type) and util.safe_issubclass(
                        item_constraint,
                        (classbuilder.ProtocolBase, classbuilder.LiteralValue))

                if not any([isdict, isklass]):
                    raise TypeError("Item constraint is not a schema")

                if isdict and '$ref' in item_constraint:
                    if klassbuilder is None:
                        raise TypeError(
                            "Cannot resolve {0} without classbuilder".format(
                                item_constraint['$ref']))

                    uri = item_constraint['$ref']
                    if uri in klassbuilder.resolved:
                        logger.debug(
                            util.lazy_format(
                                "Using previously resolved object for {0}",
                                uri))
                    else:
                        logger.debug(
                            util.lazy_format("Resolving object for {0}", uri))

                        with klassbuilder.resolver.resolving(uri) as resolved:
                            # Set incase there is a circular reference in schema definition
                            klassbuilder.resolved[uri] = None
                            klassbuilder.resolved[
                                uri] = klassbuilder.construct(
                                    uri, resolved,
                                    (classbuilder.ProtocolBase, ))

                    item_constraint = klassbuilder.resolved[uri]

                elif isdict and item_constraint.get('type') == 'array':
                    # We need to create a sub-array validator.
                    item_constraint = ArrayWrapper.create(
                        name + "#sub",
                        item_constraint=item_constraint['items'],
                        addl_constraints=item_constraint)
                elif isdict and 'oneOf' in item_constraint:
                    # We need to create a TypeProxy validator
                    uri = "{0}_{1}".format(name, "<anonymous_list_type>")
                    type_array = []
                    for i, item_detail in enumerate(item_constraint['oneOf']):
                        if '$ref' in item_detail:
                            subtype = klassbuilder.construct(
                                util.resolve_ref_uri(
                                    klassbuilder.resolver.resolution_scope,
                                    item_detail['$ref']), item_detail)
                        else:
                            subtype = klassbuilder.construct(
                                uri + "_%s" % i, item_detail)

                        type_array.append(subtype)

                    item_constraint = classbuilder.TypeProxy(type_array)

                elif isdict and item_constraint.get('type') == 'object':
                    """ We need to create a ProtocolBase object for this anonymous definition"""
                    uri = "{0}_{1}".format(name, "<anonymous_list_type>")
                    item_constraint = klassbuilder.construct(
                        uri, item_constraint)

        props['__itemtype__'] = item_constraint

        strict = addl_constraints.pop('strict', False)
        props['_strict_'] = strict
        props.update(addl_constraints)

        validator = type(str(name), (ArrayWrapper, ), props)

        return validator
    def create(name, item_constraint=None, **addl_constraints):
        """ Create an array validator based on the passed in constraints.

        If item_constraint is a tuple, it is assumed that tuple validation
        is being performed. If it is a class or dictionary, list validation
        will be performed. Classes are assumed to be subclasses of ProtocolBase,
        while dictionaries are expected to be basic types ('string', 'number', ...).

        addl_constraints is expected to be key-value pairs of any of the other
        constraints permitted by JSON Schema v4.
        """
        logger.debug(
            fmt(
                "Constructing ArrayValidator with {} and {}",
                item_constraint,
                addl_constraints,
            )
        )
        from python_jsonschema_objects import classbuilder

        klassbuilder = addl_constraints.pop(
            "classbuilder", None
        )  # type: python_jsonschema_objects.classbuilder.ClassBuilder
        props = {}

        if item_constraint is not None:
            if isinstance(item_constraint, (tuple, list)):
                for i, elem in enumerate(item_constraint):
                    isdict = isinstance(elem, (dict,))
                    isklass = isinstance(elem, type) and util.safe_issubclass(
                        elem, (classbuilder.ProtocolBase, classbuilder.LiteralValue)
                    )

                    if not any([isdict, isklass]):
                        raise TypeError(
                            "Item constraint (position {0}) is not a schema".format(i)
                        )
            elif isinstance(
                item_constraint, (classbuilder.TypeProxy, classbuilder.TypeRef)
            ):
                pass
            elif util.safe_issubclass(item_constraint, ArrayWrapper):
                pass
            else:
                isdict = isinstance(item_constraint, (dict,))
                isklass = isinstance(item_constraint, type) and util.safe_issubclass(
                    item_constraint,
                    (classbuilder.ProtocolBase, classbuilder.LiteralValue),
                )

                if not any([isdict, isklass]):
                    raise TypeError("Item constraint is not a schema")

                if isdict and "$ref" in item_constraint:
                    if klassbuilder is None:
                        raise TypeError(
                            "Cannot resolve {0} without classbuilder".format(
                                item_constraint["$ref"]
                            )
                        )

                    item_constraint = klassbuilder.resolve_type(
                        item_constraint["$ref"], name
                    )

                elif isdict and item_constraint.get("type") == "array":
                    # We need to create a sub-array validator.
                    item_constraint = ArrayWrapper.create(
                        name + "#sub",
                        item_constraint=item_constraint["items"],
                        addl_constraints=item_constraint,
                    )
                elif isdict and "oneOf" in item_constraint:
                    # We need to create a TypeProxy validator
                    uri = "{0}_{1}".format(name, "<anonymous_list_type>")
                    type_array = klassbuilder.construct_objects(
                        item_constraint["oneOf"], uri
                    )

                    item_constraint = classbuilder.TypeProxy(type_array)

                elif isdict and item_constraint.get("type") == "object":
                    """ We need to create a ProtocolBase object for this anonymous definition"""
                    uri = "{0}_{1}".format(name, "<anonymous_list_type>")
                    item_constraint = klassbuilder.construct(uri, item_constraint)

        props["__itemtype__"] = item_constraint

        strict = addl_constraints.pop("strict", False)
        props["_strict_"] = strict
        props.update(addl_constraints)

        validator = type(str(name), (ArrayWrapper,), props)

        return validator