<s> __version__ = '<STR_LIT>' <EOL> class SchemaError ( Exception ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , autos , errors ) : <EOL> self . autos = autos if type ( autos ) is list else [ autos ] <EOL> self . errors = errors if type ( errors ) is list else [ errors ] <EOL> Exception . __init__ ( self , self . code ) <EOL> @ property <EOL> def code ( self ) : <EOL> def uniq ( seq ) : <EOL> seen = set ( ) <EOL> seen_add = seen . add <EOL> return [ x for x in seq if x not in seen and not seen_add ( x ) ] <EOL> a = uniq ( i for i in self . autos if i is not None ) <EOL> e = uniq ( i for i in self . errors if i is not None ) <EOL> if e : <EOL> return '<STR_LIT:\n>' . join ( e ) <EOL> return '<STR_LIT:\n>' . join ( a ) <EOL> class And ( object ) : <EOL> def __init__ ( self , * args , ** kw ) : <EOL> self . _args = args <EOL> assert list ( kw ) in ( [ '<STR_LIT:error>' ] , [ ] ) <EOL> self . _error = kw . get ( '<STR_LIT:error>' ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , <EOL> '<STR_LIT:U+002CU+0020>' . join ( repr ( a ) for a in self . _args ) ) <EOL> def validate ( self , data ) : <EOL> for s in [ Schema ( s , error = self . _error ) for s in self . _args ] : <EOL> data = s . validate ( data ) <EOL> return data <EOL> class Or ( And ) : <EOL> def validate ( self , data ) : <EOL> x = SchemaError ( [ ] , [ ] ) <EOL> for s in [ Schema ( s , error = self . _error ) for s in self . _args ] : <EOL> try : <EOL> return s . validate ( data ) <EOL> except SchemaError as _x : <EOL> x = _x <EOL> raise SchemaError ( [ '<STR_LIT>' % ( self , data ) ] + x . autos , <EOL> [ self . _error ] + x . errors ) <EOL> class Use ( object ) : <EOL> def __init__ ( self , callable_ , error = None ) : <EOL> assert callable ( callable_ ) <EOL> self . _callable = callable_ <EOL> self . _error = error <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , self . _callable ) <EOL> def validate ( self , data ) : <EOL> try : <EOL> return self . _callable ( data ) <EOL> except SchemaError as x : <EOL> raise SchemaError ( [ None ] + x . autos , [ self . _error ] + x . errors ) <EOL> except BaseException as x : <EOL> f = self . _callable . __name__ <EOL> raise SchemaError ( '<STR_LIT>' % ( f , data , x ) , self . _error ) <EOL> def priority ( s ) : <EOL> """<STR_LIT>""" <EOL> if type ( s ) in ( list , tuple , set , frozenset ) : <EOL> return <NUM_LIT:6> <EOL> if type ( s ) is dict : <EOL> return <NUM_LIT:5> <EOL> if hasattr ( s , '<STR_LIT>' ) : <EOL> return <NUM_LIT:4> <EOL> if type ( s ) is type : <EOL> return <NUM_LIT:3> <EOL> if callable ( s ) : <EOL> return <NUM_LIT:2> <EOL> else : <EOL> return <NUM_LIT:1> <EOL> class Schema ( object ) : <EOL> def __init__ ( self , schema , error = None ) : <EOL> self . _schema = schema <EOL> self . _error = error <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , self . _schema ) <EOL> def validate ( self , data ) : <EOL> s = self . _schema <EOL> e = self . _error <EOL> if type ( s ) in ( list , tuple , set , frozenset ) : <EOL> data = Schema ( type ( s ) , error = e ) . validate ( data ) <EOL> return type ( s ) ( Or ( * s , error = e ) . validate ( d ) for d in data ) <EOL> if type ( s ) is dict : <EOL> data = Schema ( dict , error = e ) . validate ( data ) <EOL> new = type ( data ) ( ) <EOL> x = None <EOL> coverage = set ( ) <EOL> sorted_skeys = list ( sorted ( s , key = priority ) ) <EOL> for key , value in data . items ( ) : <EOL> valid = False <EOL> skey = None <EOL> for skey in sorted_skeys : <EOL> svalue = s [ skey ] <EOL> try : <EOL> nkey = Schema ( skey , error = e ) . validate ( key ) <EOL> except SchemaError : <EOL> pass <EOL> else : <EOL> try : <EOL> nvalue = Schema ( svalue , error = e ) . validate ( value ) <EOL> except SchemaError as _x : <EOL> x = _x <EOL> raise <EOL> else : <EOL> coverage . add ( skey ) <EOL> valid = True <EOL> break <EOL> if valid : <EOL> new [ nkey ] = nvalue <EOL> elif skey is not None : <EOL> if x is not None : <EOL> raise SchemaError ( [ '<STR_LIT>' % key ] + <EOL> x . autos , [ e ] + x . errors ) <EOL> coverage = set ( k for k in coverage if type ( k ) is not Optional ) <EOL> required = set ( k for k in s if type ( k ) is not Optional ) <EOL> if coverage != required : <EOL> raise SchemaError ( '<STR_LIT>' % ( required - coverage ) , e ) <EOL> if len ( new ) != len ( data ) : <EOL> wrong_keys = set ( data . keys ( ) ) - set ( new . keys ( ) ) <EOL> s_wrong_keys = '<STR_LIT:U+002CU+0020>' . join ( '<STR_LIT>' % k for k in sorted ( wrong_keys ) ) <EOL> raise SchemaError ( '<STR_LIT>' % ( s_wrong_keys , data ) , <EOL> e ) <EOL> return new <EOL> if hasattr ( s , '<STR_LIT>' ) : <EOL> try : <EOL> return s . validate ( data ) <EOL> except SchemaError as x : <EOL> raise SchemaError ( [ None ] + x . autos , [ e ] + x . errors ) <EOL> except BaseException as x : <EOL> raise SchemaError ( '<STR_LIT>' % ( s , data , x ) , <EOL> self . _error ) <EOL> if type ( s ) is type : <EOL> if isinstance ( data , s ) : <EOL> return data <EOL> else : <EOL> raise SchemaError ( '<STR_LIT>' % ( data , s ) , e ) <EOL> if callable ( s ) : <EOL> f = s . __name__ <EOL> try : <EOL> if s ( data ) : <EOL> return data <EOL> except SchemaError as x : <EOL> raise SchemaError ( [ None ] + x . autos , [ e ] + x . errors ) <EOL> except BaseException as x : <EOL> raise SchemaError ( '<STR_LIT>' % ( f , data , x ) , <EOL> self . _error ) <EOL> raise SchemaError ( '<STR_LIT>' % ( f , data ) , e ) <EOL> if s == data : <EOL> return data <EOL> else : <EOL> raise SchemaError ( '<STR_LIT>' % ( s , data ) , e ) <EOL> class Optional ( Schema ) : <EOL> """<STR_LIT>""" </s>
