<s> from yota . renderers import JinjaRenderer <EOL> from yota . processors import FlaskPostProcessor <EOL> from yota . nodes import LeaderNode , Node <EOL> from yota . validators import Check , Listener <EOL> import json <EOL> import copy <EOL> class TrackingMeta ( type ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( mcs , name , bases , dct ) : <EOL> """<STR_LIT>""" <EOL> nodes = { } <EOL> mcs . _validation_list = [ ] <EOL> mcs . _node_list = [ ] <EOL> mcs . _event_lists = { } <EOL> for name , attribute in dct . items ( ) : <EOL> if name is '<STR_LIT:start>' or name is '<STR_LIT>' : <EOL> try : <EOL> attribute . _attr_name = name <EOL> except AttributeError : <EOL> raise AttributeError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" . format ( type ( name ) ) ) <EOL> continue <EOL> if isinstance ( attribute , Node ) : <EOL> attribute . _attr_name = name <EOL> nodes [ attribute . _create_counter ] = attribute <EOL> delattr ( mcs , name ) <EOL> elif isinstance ( attribute , Check ) : <EOL> attribute . _attr_name = name <EOL> mcs . _validation_list . append ( attribute ) <EOL> delattr ( mcs , name ) <EOL> elif isinstance ( attribute , Listener ) : <EOL> attribute . _attr_name = name <EOL> if attribute . type not in mcs . _event_lists : <EOL> mcs . _event_lists [ attribute . type ] = [ ] <EOL> mcs . _event_lists [ attribute . type ] . append ( attribute ) <EOL> delattr ( mcs , name ) <EOL> else : <EOL> try : <EOL> for node in attribute . _node_list : <EOL> nodes [ node . _create_counter ] = node <EOL> except AttributeError : <EOL> pass <EOL> try : <EOL> for key , lst in attribute . _event_lists . items ( ) : <EOL> if key in mcs . _event_lists : <EOL> mcs . _event_lists [ key ] . extend ( lst ) <EOL> else : <EOL> mcs . _event_lists [ key ] = lst <EOL> except AttributeError : <EOL> pass <EOL> try : <EOL> mcs . _validation_list . extend ( attribute . _validation_list ) <EOL> except AttributeError : <EOL> pass <EOL> for i , attribute in sorted ( nodes . items ( ) ) : <EOL> mcs . _node_list . append ( attribute ) <EOL> _Form = TrackingMeta ( '<STR_LIT>' , ( object , ) , { } ) <EOL> class Form ( _Form ) : <EOL> """<STR_LIT>""" <EOL> __metaclass__ = TrackingMeta <EOL> _renderer = JinjaRenderer <EOL> """<STR_LIT>""" <EOL> _processor = FlaskPostProcessor <EOL> """<STR_LIT>""" <EOL> _reserved_attr_names = ( '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT:name>' ) <EOL> name = None <EOL> context = { } <EOL> g_context = { } <EOL> title = None <EOL> auto_start_close = True <EOL> start_template = '<STR_LIT>' <EOL> close_template = '<STR_LIT>' <EOL> render_success = False <EOL> render_error = False <EOL> type_class_map = { '<STR_LIT:error>' : '<STR_LIT>' , <EOL> '<STR_LIT:info>' : '<STR_LIT>' , <EOL> '<STR_LIT:success>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' } <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , ** kwargs ) : <EOL> for class_attr in dir ( self ) : <EOL> if class_attr in kwargs : <EOL> continue <EOL> att = getattr ( self , class_attr ) <EOL> if class_attr in [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] : <EOL> setattr ( self , class_attr , copy . deepcopy ( att ) ) <EOL> elif not class_attr . startswith ( '<STR_LIT>' ) : <EOL> if not callable ( att ) : <EOL> setattr ( self , class_attr , copy . copy ( att ) ) <EOL> self . context [ class_attr ] = att <EOL> if self . name is None : <EOL> self . name = self . __class__ . __name__ <EOL> self . context [ '<STR_LIT:name>' ] = self . name <EOL> self . context [ '<STR_LIT:title>' ] = self . title <EOL> for node in self . _node_list : <EOL> self . _setup_node ( node ) <EOL> self . context . update ( kwargs ) <EOL> self . __dict__ . update ( kwargs ) <EOL> if hasattr ( self , '<STR_LIT:start>' ) : <EOL> self . _node_list . insert ( <NUM_LIT:0> , self . start ) <EOL> else : <EOL> if self . auto_start_close : <EOL> self . insert ( <NUM_LIT:0> , LeaderNode ( template = self . start_template , <EOL> _attr_name = '<STR_LIT:start>' , <EOL> ** self . context ) ) <EOL> if hasattr ( self , '<STR_LIT>' ) : <EOL> self . _node_list . append ( self . close ) <EOL> else : <EOL> if self . auto_start_close : <EOL> self . insert ( - <NUM_LIT:1> , LeaderNode ( template = self . close_template , <EOL> _attr_name = '<STR_LIT>' , <EOL> ** self . context ) ) <EOL> default_globals = { '<STR_LIT>' : self . name } <EOL> default_globals . update ( self . g_context ) <EOL> self . g_context = default_globals <EOL> self . _last_valid = None <EOL> self . _last_raw_json = None <EOL> def render ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _process_errors ( ) <EOL> return self . _renderer ( ) . render ( self . _node_list , self . g_context ) <EOL> def add_listener ( self , listener , type ) : <EOL> """<STR_LIT>""" <EOL> if type not in self . _event_lists : <EOL> self . _event_lists [ type ] = [ ] <EOL> self . _event_lists [ type ] . append ( listener ) <EOL> def trigger_event ( self , type ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> for event in self . _event_lists [ type ] : <EOL> event . resolve_attr_names ( self ) <EOL> event ( ) <EOL> except KeyError : <EOL> pass <EOL> def _setup_node ( self , node ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> if type ( node . _attr_name ) is not str : <EOL> raise AttributeError <EOL> except AttributeError as e : <EOL> raise AttributeError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> if hasattr ( self , node . _attr_name ) : <EOL> raise AttributeError ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( node . _attr_name ) ) <EOL> node . set_identifiers ( self . name ) <EOL> setattr ( self , node . _attr_name , node ) <EOL> def _parse_shorthand_validator ( self , node ) : <EOL> """<STR_LIT>""" <EOL> if hasattr ( node , '<STR_LIT>' ) and node . validators : <EOL> if callable ( node . validators ) : <EOL> node . validators = ( node . validators , ) <EOL> for validator in node . validators : <EOL> if isinstance ( validator , Check ) : <EOL> if not validator . args and not validator . kwargs : <EOL> validator . args . append ( node . _attr_name ) <EOL> self . _validation_list . append ( validator ) <EOL> else : <EOL> new_valid = Check ( validator , node . _attr_name ) <EOL> self . _validation_list . append ( new_valid ) <EOL> delattr ( node , '<STR_LIT>' ) <EOL> def _process_errors ( self ) : <EOL> for node in self . _node_list : <EOL> for error in node . errors : <EOL> try : <EOL> error [ '<STR_LIT>' ] = self . type_class_map [ error [ '<STR_LIT:type>' ] ] <EOL> except KeyError : <EOL> error [ '<STR_LIT>' ] = self . type_class_map [ '<STR_LIT:error>' ] <EOL> def insert_validator ( self , new_validators ) : <EOL> """<STR_LIT>""" <EOL> for validator in new_validators : <EOL> if not isinstance ( validator , Check ) : <EOL> raise TypeError ( '<STR_LIT>' ) <EOL> self . _validation_list . append ( validator ) <EOL> def insert ( self , position , new_node_list ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( new_node_list , Node ) : <EOL> new_node_list = ( new_node_list , ) <EOL> for i , new_node in enumerate ( new_node_list ) : <EOL> self . _setup_node ( new_node ) <EOL> if position == - <NUM_LIT:1> : <EOL> self . _node_list . append ( new_node ) <EOL> else : <EOL> self . _node_list . insert ( position + i , new_node ) <EOL> def insert_after ( self , prev_attr_name , new_node_list ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( new_node_list , Node ) : <EOL> new_node_list = ( new_node_list , ) <EOL> for index , node in enumerate ( self . _node_list ) : <EOL> if node . _attr_name == prev_attr_name : <EOL> for i , new_node in enumerate ( new_node_list ) : <EOL> self . _node_list . insert ( index + i + <NUM_LIT:1> , new_node ) <EOL> setattr ( self , new_node . _attr_name , new_node ) <EOL> new_node . set_identifiers ( self . name ) <EOL> break <EOL> else : <EOL> for new_node in new_node_list : <EOL> self . _node_list . append ( new_node ) <EOL> def get_by_attr ( self , name ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> attr = getattr ( self , name ) <EOL> except AttributeError : <EOL> pass <EOL> else : <EOL> if isinstance ( attr , Node ) : <EOL> return attr <EOL> raise AttributeError ( '<STR_LIT>' <EOL> '<STR_LIT>' . format ( name ) ) <EOL> def success_header_generate ( self ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def error_header_generate ( self , errors , block ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def data_by_attr ( self ) : <EOL> """<STR_LIT>""" <EOL> ret = { } <EOL> for node in self . _node_list : <EOL> ret [ node . _attr_name ] = node . data <EOL> return ret <EOL> def data_by_name ( self ) : <EOL> """<STR_LIT>""" <EOL> ret = { } <EOL> for node in self . _node_list : <EOL> ret [ node . name ] = node . data <EOL> return ret <EOL> def _gen_validate ( self , data , piecewise = False ) : <EOL> """<STR_LIT>""" <EOL> data = self . _processor ( ) . filter_post ( data ) <EOL> for node in self . _node_list : <EOL> node . errors = [ ] <EOL> node . data = '<STR_LIT>' <EOL> node . resolve_data ( data ) <EOL> self . _parse_shorthand_validator ( node ) <EOL> if '<STR_LIT>' not in data and piecewise : <EOL> raise AttributeError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> elif piecewise : <EOL> visited = json . loads ( data [ '<STR_LIT>' ] ) <EOL> block = False <EOL> for check in self . _validation_list : <EOL> check . resolve_attr_names ( self ) <EOL> if piecewise is False or check . node_visited ( visited ) : <EOL> check ( ) <EOL> else : <EOL> block = True <EOL> self . validator ( ) <EOL> error_node_list = [ ] <EOL> for node in self . _node_list : <EOL> if node . errors : <EOL> error_node_list . append ( node ) <EOL> for error in node . errors : <EOL> block |= error . get ( '<STR_LIT>' , True ) <EOL> return block , error_node_list <EOL> def json_validate ( self , data , piecewise = False , raw = False ) : <EOL> """<STR_LIT>""" <EOL> data = self . _processor ( ) . filter_post ( data ) <EOL> errors = { } <EOL> """<STR_LIT>""" <EOL> if data . get ( '<STR_LIT>' , '<STR_LIT:false>' ) != '<STR_LIT:true>' and piecewise : <EOL> block , invalid = self . _gen_validate ( data , piecewise = piecewise ) <EOL> block = True <EOL> else : <EOL> block , invalid = self . _gen_validate ( data , piecewise = False ) <EOL> for node in invalid : <EOL> errors [ node . _attr_name ] = { '<STR_LIT>' : node . json_identifiers ( ) , <EOL> '<STR_LIT>' : node . errors } <EOL> retval = { '<STR_LIT>' : block } <EOL> if len ( errors ) > <NUM_LIT:0> : <EOL> header_err = self . error_header_generate ( errors , block ) <EOL> if header_err : <EOL> errors [ '<STR_LIT:start>' ] = { '<STR_LIT>' : self . start . json_identifiers ( ) , <EOL> '<STR_LIT>' : header_err } <EOL> if not block : <EOL> blob = self . success_header_generate ( ) <EOL> if blob : <EOL> retval [ '<STR_LIT>' ] = blob <EOL> if hasattr ( self , '<STR_LIT:start>' ) : <EOL> retval [ '<STR_LIT>' ] = self . start . json_identifiers ( ) <EOL> retval [ '<STR_LIT>' ] = errors <EOL> if data . get ( '<STR_LIT>' , '<STR_LIT:false>' ) == '<STR_LIT:true>' and not block : <EOL> valid = True <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> else : <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> valid = False <EOL> self . _last_raw_json = retval <EOL> self . _process_errors ( ) <EOL> if raw : <EOL> return valid , retval <EOL> else : <EOL> return valid , json . dumps ( retval ) <EOL> def validate ( self , data ) : <EOL> """<STR_LIT>""" <EOL> data = self . _processor ( ) . filter_post ( data ) <EOL> block , invalid = self . _gen_validate ( data ) <EOL> if block : <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> else : <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> return ( not block ) , invalid <EOL> def validate_render ( self , data ) : <EOL> """<STR_LIT>""" <EOL> data = self . _processor ( ) . filter_post ( data ) <EOL> block , invalid = self . _gen_validate ( data ) <EOL> self . g_context [ '<STR_LIT>' ] = block <EOL> self . _last_valid = '<STR_LIT>' <EOL> if not block : <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> self . success_header_generate ( ) <EOL> else : <EOL> self . trigger_event ( "<STR_LIT>" ) <EOL> self . error_header_generate ( invalid , block ) <EOL> return ( not block ) , self . render ( ) <EOL> def validator ( self ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def update_success ( self , update_dict , raw = False ) : <EOL> """<STR_LIT>""" <EOL> if self . _last_valid == '<STR_LIT>' : <EOL> try : <EOL> self . start . errors [ - <NUM_LIT:1> ] . update ( update_dict ) <EOL> except IndexError : <EOL> raise IndexError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> except AttributeError : <EOL> raise AttributeError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> return self . render ( ) <EOL> else : <EOL> try : <EOL> self . _last_raw_json [ '<STR_LIT>' ] . update ( update_dict ) <EOL> except KeyError : <EOL> raise KeyError ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> if raw : <EOL> return self . _last_raw_json <EOL> else : <EOL> return json . dumps ( self . _last_raw_json ) </s>
