from jsonschema import _utils
from jsonschema . exceptions import ValidationError
def id_of_ignore_ref ( property = " $id " ) :
def id_of ( schema ) :
"""
Ignore an ` ` $ id ` ` sibling of ` ` $ ref ` ` if it is present .
Otherwise , return the ID of the given schema .
"""
if schema is True or schema is False or " $ref " in schema :
return " "
return schema . get ( property , " " )
return id_of
def ignore_ref_siblings ( schema ) :
"""
Ignore siblings of ` ` $ ref ` ` if it is present .
Otherwise , return all keywords .
Suitable for use with ` create ` ' s ``applicable_validators`` argument.
"""
ref = schema . get ( " $ref " )
if ref is not None :
return [ ( " $ref " , ref ) ]
else :
return schema . items ( )
def dependencies_draft3 ( validator , dependencies , instance , schema ) :
if not validator . is_type ( instance , " object " ) :
return
for property , dependency in dependencies . items ( ) :
if property not in instance :
continue
if validator . is_type ( dependency , " object " ) :
yield from validator . descend (
instance , dependency , schema_path = property ,
)
elif validator . is_type ( dependency , " string " ) :
if dependency not in instance :
message = f " { dependency !r} is a dependency of { property !r} "
yield ValidationError ( message )
else :
for each in dependency :
if each not in instance :
message = f " { each !r} is a dependency of { property !r} "
yield ValidationError ( message )
def dependencies_draft4_draft6_draft7 (
validator ,
dependencies ,
instance ,
schema ,
) :
"""
Support for the ` ` dependencies ` ` keyword from pre - draft 2019 - 09.
In later drafts , the keyword was split into separate
` ` dependentRequired ` ` and ` ` dependentSchemas ` ` validators .
"""
if not validator . is_type ( instance , " object " ) :
return
for property , dependency in dependencies . items ( ) :
if property not in instance :
continue
if validator . is_type ( dependency , " array " ) :
for each in dependency :
if each not in instance :
message = f " { each !r} is a dependency of { property !r} "
yield ValidationError ( message )
else :
yield from validator . descend (
instance , dependency , schema_path = property ,
)
def disallow_draft3 ( validator , disallow , instance , schema ) :
for disallowed in _utils . ensure_list ( disallow ) :
if validator . evolve ( schema = { " type " : [ disallowed ] } ) . is_valid ( instance ) :
message = f " { disallowed !r} is disallowed for { instance !r} "
yield ValidationError ( message )
def extends_draft3 ( validator , extends , instance , schema ) :
if validator . is_type ( extends , " object " ) :
yield from validator . descend ( instance , extends )
return
for index , subschema in enumerate ( extends ) :
yield from validator . descend ( instance , subschema , schema_path = index )
def items_draft3_draft4 ( validator , items , instance , schema ) :
if not validator . is_type ( instance , " array " ) :
return
if validator . is_type ( items , " object " ) :
for index , item in enumerate ( instance ) :
yield from validator . descend ( item , items , path = index )
else :
for ( index , item ) , subschema in zip ( enumerate ( instance ) , items ) :
yield from validator . descend (
item , subschema , path = index , schema_path = index ,
)
def items_draft6_draft7_draft201909 ( validator , items , instance , schema ) :
if not validator . is_type ( instance , " array " ) :
return
if validator . is_type ( items , " array " ) :
for ( index , item ) , subschema in zip ( enumerate ( instance ) , items ) :
yield from validator . descend (
item , subschema , path = index , schema_path = index ,
)
else :
for index , item in enumerate ( instance ) :
yield from validator . descend ( item , items , path = index )
def minimum_draft3_draft4 ( validator , minimum , instance , schema ) :
if not validator . is_type ( instance , " number " ) :
return
if schema . get ( " exclusiveMinimum " , False ) :
failed = instance < = minimum
cmp = " less than or equal to "
else :
failed = instance < minimum
cmp = " less than "
if failed :
message = f " { instance !r} is { cmp } the minimum of { minimum !r} "
yield ValidationError ( message )
def maximum_draft3_draft4 ( validator , maximum , instance , schema ) :
if not validator . is_type ( instance , " number " ) :
return
if schema . get ( " exclusiveMaximum " , False ) :
failed = instance > = maximum
cmp = " greater than or equal to "
else :
failed = instance > maximum
cmp = " greater than "
if failed :
message = f " { instance !r} is { cmp } the maximum of { maximum !r} "
yield ValidationError ( message )
def properties_draft3 ( validator , properties , instance , schema ) :
if not validator . is_type ( instance , " object " ) :
return
for property , subschema in properties . items ( ) :
if property in instance :
yield from validator . descend (
instance [ property ] ,
subschema ,
path = property ,
schema_path = property ,
)
elif subschema . get ( " required " , False ) :
error = ValidationError ( f " { property !r} is a required property " )
error . _set (
validator = " required " ,
validator_value = subschema [ " required " ] ,
instance = instance ,
schema = schema ,
)
error . path . appendleft ( property )
error . schema_path . extend ( [ property , " required " ] )
yield error
def type_draft3 ( validator , types , instance , schema ) :
types = _utils . ensure_list ( types )
all_errors = [ ]
for index , type in enumerate ( types ) :
if validator . is_type ( type , " object " ) :
errors = list ( validator . descend ( instance , type , schema_path = index ) )
if not errors :
return
all_errors . extend ( errors )
else :
if validator . is_type ( instance , type ) :
return
else :
reprs = [ ]
for type in types :
try :
reprs . append ( repr ( type [ " name " ] ) )
except Exception :
reprs . append ( repr ( type ) )
yield ValidationError (
f " { instance !r} is not of type { ' , ' . join ( reprs ) } " ,
context = all_errors ,
)
def contains_draft6_draft7 ( validator , contains , instance , schema ) :
if not validator . is_type ( instance , " array " ) :
return
if not any (
validator . evolve ( schema = contains ) . is_valid ( element )
for element in instance
) :
yield ValidationError (
f " None of { instance !r} are valid under the given schema " ,
)
def recursiveRef ( validator , recursiveRef , instance , schema ) :
lookup_url , target = validator . resolver . resolution_scope , validator . schema
for each in reversed ( validator . resolver . _scopes_stack [ 1 : ] ) :
lookup_url , next_target = validator . resolver . resolve ( each )
if next_target . get ( " $recursiveAnchor " ) :
target = next_target
else :
break
fragment = recursiveRef . lstrip ( " # " )
subschema = validator . resolver . resolve_fragment ( target , fragment )
# FIXME: This is gutted (and not calling .descend) because it can trigger
# recursion errors, so there's a bug here. Re-enable the tests to
# see it.
subschema
return [ ]
def find_evaluated_item_indexes_by_schema ( validator , instance , schema ) :
"""
Get all indexes of items that get evaluated under the current schema
Covers all keywords related to unevaluatedItems : items , prefixItems , if ,
then , else , contains , unevaluatedItems , allOf , oneOf , anyOf
"""
if validator . is_type ( schema , " boolean " ) :
return [ ]
evaluated_indexes = [ ]
if " additionalItems " in schema :
return list ( range ( 0 , len ( instance ) ) )
if " $ref " in schema :
scope , resolved = validator . resolver . resolve ( schema [ " $ref " ] )
validator . resolver . push_scope ( scope )
try :
evaluated_indexes + = find_evaluated_item_indexes_by_schema (
validator , instance , resolved ,
)
finally :
validator . resolver . pop_scope ( )
if " items " in schema :
if validator . is_type ( schema [ " items " ] , " object " ) :
return list ( range ( 0 , len ( instance ) ) )
evaluated_indexes + = list ( range ( 0 , len ( schema [ " items " ] ) ) )
if " if " in schema :
if validator . evolve ( schema = schema [ " if " ] ) . is_valid ( instance ) :
evaluated_indexes + = find_evaluated_item_indexes_by_schema (
validator , instance , schema [ " if " ] ,
)
if " then " in schema :
evaluated_indexes + = find_evaluated_item_indexes_by_schema (
validator , instance , schema [ " then " ] ,
)
else :
if " else " in schema :
evaluated_indexes + = find_evaluated_item_indexes_by_schema (
validator , instance , schema [ " else " ] ,
)
for keyword in [ " contains " , " unevaluatedItems " ] :
if keyword in schema :
for k , v in enumerate ( instance ) :
if validator . evolve ( schema = schema [ keyword ] ) . is_valid ( v ) :
evaluated_indexes . append ( k )
for keyword in [ " allOf " , " oneOf " , " anyOf " ] :
if keyword in schema :
for subschema in schema [ keyword ] :
errs = list ( validator . descend ( instance , subschema ) )
if not errs :
evaluated_indexes + = find_evaluated_item_indexes_by_schema (
validator , instance , subschema ,
)
return evaluated_indexes
def unevaluatedItems_draft2019 ( validator , unevaluatedItems , instance , schema ) :
if not validator . is_type ( instance , " array " ) :
return
evaluated_item_indexes = find_evaluated_item_indexes_by_schema (
validator , instance , schema ,
)
unevaluated_items = [
item for index , item in enumerate ( instance )
if index not in evaluated_item_indexes
]
if unevaluated_items :
error = " Unevaluated items are not allowed ( %s %s unexpected) "
yield ValidationError ( error % _utils . extras_msg ( unevaluated_items ) )