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