コード例 #1
0
    def __init__(self, ary):
        """Initialize a wrapper for the array

        Args:
            ary: (list-like, or ArrayWrapper)
        """
        """ Marks whether or not the underlying array has been modified """
        self._dirty = True
        """ Holds a typed copy of the array """
        self._typed = None

        if isinstance(ary, (list, tuple, collections.abc.Sequence)):
            self.data = ary
        else:
            raise TypeError(
                "Invalid value given to array validator: {0}".format(ary))

        logger.debug(fmt("Initializing ArrayWrapper {} with {}", self, ary))
コード例 #2
0
    def __init__(self, ary):
        """ Initialize a wrapper for the array

        Args:
            ary: (list-like, or ArrayWrapper)
        """

        """ Marks whether or not the underlying array has been modified """
        self._dirty = True

        """ Holds a typed copy of the array """
        self._typed = None

        if isinstance(ary, (list, tuple, collections.Sequence)):
            self.data = ary
        elif isinstance(ary, ArrayWrapper):
            self.data = ary.data
        else:
            raise TypeError("Invalid value given to array validator: {0}"
                            .format(ary))

        logger.debug(fmt("Initializing ArrayWrapper {} with {}", self, ary))
コード例 #3
0
    def typed_elems(self):
        logger.debug(fmt("Accessing typed_elems of ArrayWrapper {} ", self))
        if self._typed is None or self._dirty is True:
            self.validate()

        return self._typed
コード例 #4
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
コード例 #5
0
    def validate_items(self):
        """ Validates the items in the backing array, including
        performing type validation.

        Sets the _typed property and clears the dirty flag as a side effect

        Returns:
            The typed array
        """
        logger.debug(fmt("Validating {}", self))
        from python_jsonschema_objects import classbuilder

        if self.__itemtype__ is None:
            return

        type_checks = self.__itemtype__
        if not isinstance(type_checks, (tuple, list)):
            # we were given items = {'type': 'blah'} ; thus ensure the type for all data.
            type_checks = [type_checks] * len(self.data)
        elif len(type_checks) > len(self.data):
            raise ValidationError(
                "{1} does not have sufficient elements to validate against {0}"
                .format(self.__itemtype__, self.data))

        typed_elems = []
        for elem, typ in zip(self.data, type_checks):
            if isinstance(typ, dict):
                for param, paramval in six.iteritems(typ):
                    validator = registry(param)
                    if validator is not None:
                        validator(paramval, elem, typ)
                typed_elems.append(elem)

            elif util.safe_issubclass(typ, classbuilder.LiteralValue):
                val = typ(elem)
                val.validate()
                typed_elems.append(val)
            elif util.safe_issubclass(typ, classbuilder.ProtocolBase):
                if not isinstance(elem, typ):
                    try:
                        if isinstance(
                                elem,
                            (six.string_types, six.integer_types, float)):
                            val = typ(elem)
                        else:
                            val = typ(**util.coerce_for_expansion(elem))
                    except TypeError as e:
                        raise ValidationError(
                            "'{0}' is not a valid value for '{1}': {2}".format(
                                elem, typ, e))
                else:
                    val = elem
                val.validate()
                typed_elems.append(val)

            elif util.safe_issubclass(typ, ArrayWrapper):
                val = typ(elem)
                val.validate()
                typed_elems.append(val)

            elif isinstance(typ,
                            (classbuilder.TypeProxy, classbuilder.TypeRef)):
                try:
                    if isinstance(
                            elem,
                        (six.string_types, six.integer_types, float)):
                        val = typ(elem)
                    else:
                        val = typ(**util.coerce_for_expansion(elem))
                except TypeError as e:
                    raise ValidationError(
                        "'{0}' is not a valid value for '{1}': {2}".format(
                            elem, typ, e))
                else:
                    val.validate()
                    typed_elems.append(val)

        self._dirty = False
        self._typed = typed_elems
        return typed_elems
コード例 #6
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
        )  # 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
コード例 #7
0
    def typed_elems(self):
        logger.debug(fmt("Accessing typed_elems of ArrayWrapper {} ", self))
        if self._typed is None or self._dirty is True:
            self.validate()

        return self._typed
コード例 #8
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
コード例 #9
0
    def validate_items(self):
        """ Validates the items in the backing array, including
        performing type validation.

        Sets the _typed property and clears the dirty flag as a side effect

        Returns:
            The typed array
        """
        logger.debug(fmt("Validating {}", self))
        from python_jsonschema_objects import classbuilder

        if self.__itemtype__ is None:
            return

        type_checks = self.__itemtype__
        if not isinstance(type_checks, (tuple, list)):
            # we were given items = {'type': 'blah'} ; thus ensure the type for all data.
            type_checks = [type_checks] * len(self.data)
        elif len(type_checks) > len(self.data):
            raise ValidationError(
                "{1} does not have sufficient elements to validate against {0}"
                .format(self.__itemtype__, self.data))

        typed_elems = []
        for elem, typ in zip(self.data, type_checks):
            if isinstance(typ, dict):
                for param, paramval in six.iteritems(typ):
                    validator = registry(param)
                    if validator is not None:
                        validator(paramval, elem, typ)
                typed_elems.append(elem)

            elif util.safe_issubclass(typ, classbuilder.LiteralValue):
                val = typ(elem)
                val.validate()
                typed_elems.append(val)
            elif util.safe_issubclass(typ, classbuilder.ProtocolBase):
                if not isinstance(elem, typ):
                    try:
                        if isinstance(elem, (six.string_types, six.integer_types, float)):
                            val = typ(elem)
                        else:
                            val = typ(**util.coerce_for_expansion(elem))
                    except TypeError as e:
                        raise ValidationError("'{0}' is not a valid value for '{1}': {2}"
                                              .format(elem, typ, e))
                else:
                    val = elem
                val.validate()
                typed_elems.append(val)

            elif util.safe_issubclass(typ, ArrayWrapper):
                val = typ(elem)
                val.validate()
                typed_elems.append(val)

            elif isinstance(typ, (classbuilder.TypeProxy, classbuilder.TypeRef)):
                try:
                    if isinstance(elem, (six.string_types, six.integer_types, float)):
                        val = typ(elem)
                    else:
                        val = typ(**util.coerce_for_expansion(elem))
                except TypeError as e:
                    raise ValidationError("'{0}' is not a valid value for '{1}': {2}"
                                          .format(elem, typ, e))
                else:
                    val.validate()
                    typed_elems.append(val)

        self._dirty = False
        self._typed = typed_elems
        return typed_elems