<s> """<STR_LIT>""" <EOL> from . . import log , util , exc <EOL> from . . sql import operators <EOL> from . import ( <EOL> attributes , object_session , util as orm_util , strategies , <EOL> object_mapper , exc as orm_exc , properties <EOL> ) <EOL> from . query import Query <EOL> @ log . class_logger <EOL> @ properties . RelationshipProperty . strategy_for ( lazy = "<STR_LIT>" ) <EOL> class DynaLoader ( strategies . AbstractRelationshipLoader ) : <EOL> def init_class_attribute ( self , mapper ) : <EOL> self . is_class_level = True <EOL> if not self . uselist : <EOL> raise exc . InvalidRequestError ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % self . parent_property ) <EOL> strategies . _register_attribute ( <EOL> self , <EOL> mapper , <EOL> useobject = True , <EOL> uselist = True , <EOL> impl_class = DynamicAttributeImpl , <EOL> target_mapper = self . parent_property . mapper , <EOL> order_by = self . parent_property . order_by , <EOL> query_class = self . parent_property . query_class , <EOL> backref = self . parent_property . back_populates , <EOL> ) <EOL> class DynamicAttributeImpl ( attributes . AttributeImpl ) : <EOL> uses_objects = True <EOL> accepts_scalar_loader = False <EOL> supports_population = False <EOL> collection = False <EOL> def __init__ ( self , class_ , key , typecallable , <EOL> dispatch , <EOL> target_mapper , order_by , query_class = None , ** kw ) : <EOL> super ( DynamicAttributeImpl , self ) . __init__ ( class_ , key , typecallable , dispatch , ** kw ) <EOL> self . target_mapper = target_mapper <EOL> self . order_by = order_by <EOL> if not query_class : <EOL> self . query_class = AppenderQuery <EOL> elif AppenderMixin in query_class . mro ( ) : <EOL> self . query_class = query_class <EOL> else : <EOL> self . query_class = mixin_user_query ( query_class ) <EOL> def get ( self , state , dict_ , passive = attributes . PASSIVE_OFF ) : <EOL> if not passive & attributes . SQL_OK : <EOL> return self . _get_collection_history ( <EOL> state , attributes . PASSIVE_NO_INITIALIZE ) . added_items <EOL> else : <EOL> return self . query_class ( self , state ) <EOL> def get_collection ( self , state , dict_ , user_data = None , <EOL> passive = attributes . PASSIVE_NO_INITIALIZE ) : <EOL> if not passive & attributes . SQL_OK : <EOL> return self . _get_collection_history ( state , <EOL> passive ) . added_items <EOL> else : <EOL> history = self . _get_collection_history ( state , passive ) <EOL> return history . added_plus_unchanged <EOL> @ util . memoized_property <EOL> def _append_token ( self ) : <EOL> return attributes . Event ( self , attributes . OP_APPEND ) <EOL> @ util . memoized_property <EOL> def _remove_token ( self ) : <EOL> return attributes . Event ( self , attributes . OP_REMOVE ) <EOL> def fire_append_event ( self , state , dict_ , value , initiator , <EOL> collection_history = None ) : <EOL> if collection_history is None : <EOL> collection_history = self . _modified_event ( state , dict_ ) <EOL> collection_history . add_added ( value ) <EOL> for fn in self . dispatch . append : <EOL> value = fn ( state , value , initiator or self . _append_token ) <EOL> if self . trackparent and value is not None : <EOL> self . sethasparent ( attributes . instance_state ( value ) , state , True ) <EOL> def fire_remove_event ( self , state , dict_ , value , initiator , <EOL> collection_history = None ) : <EOL> if collection_history is None : <EOL> collection_history = self . _modified_event ( state , dict_ ) <EOL> collection_history . add_removed ( value ) <EOL> if self . trackparent and value is not None : <EOL> self . sethasparent ( attributes . instance_state ( value ) , state , False ) <EOL> for fn in self . dispatch . remove : <EOL> fn ( state , value , initiator or self . _remove_token ) <EOL> def _modified_event ( self , state , dict_ ) : <EOL> if self . key not in state . committed_state : <EOL> state . committed_state [ self . key ] = CollectionHistory ( self , state ) <EOL> state . _modified_event ( dict_ , <EOL> self , <EOL> attributes . NEVER_SET ) <EOL> dict_ [ self . key ] = True <EOL> return state . committed_state [ self . key ] <EOL> def set ( self , state , dict_ , value , initiator , <EOL> passive = attributes . PASSIVE_OFF , <EOL> check_old = None , pop = False ) : <EOL> if initiator and initiator . parent_token is self . parent_token : <EOL> return <EOL> if pop and value is None : <EOL> return <EOL> self . _set_iterable ( state , dict_ , value ) <EOL> def _set_iterable ( self , state , dict_ , iterable , adapter = None ) : <EOL> new_values = list ( iterable ) <EOL> if state . has_identity : <EOL> old_collection = util . IdentitySet ( self . get ( state , dict_ ) ) <EOL> collection_history = self . _modified_event ( state , dict_ ) <EOL> if not state . has_identity : <EOL> old_collection = collection_history . added_items <EOL> else : <EOL> old_collection = old_collection . union ( <EOL> collection_history . added_items ) <EOL> idset = util . IdentitySet <EOL> constants = old_collection . intersection ( new_values ) <EOL> additions = idset ( new_values ) . difference ( constants ) <EOL> removals = old_collection . difference ( constants ) <EOL> for member in new_values : <EOL> if member in additions : <EOL> self . fire_append_event ( state , dict_ , member , None , <EOL> collection_history = collection_history ) <EOL> for member in removals : <EOL> self . fire_remove_event ( state , dict_ , member , None , <EOL> collection_history = collection_history ) <EOL> def delete ( self , * args , ** kwargs ) : <EOL> raise NotImplementedError ( ) <EOL> def set_committed_value ( self , state , dict_ , value ) : <EOL> raise NotImplementedError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> def get_history ( self , state , dict_ , passive = attributes . PASSIVE_OFF ) : <EOL> c = self . _get_collection_history ( state , passive ) <EOL> return c . as_history ( ) <EOL> def get_all_pending ( self , state , dict_ , <EOL> passive = attributes . PASSIVE_NO_INITIALIZE ) : <EOL> c = self . _get_collection_history ( <EOL> state , passive ) <EOL> return [ <EOL> ( attributes . instance_state ( x ) , x ) <EOL> for x in <EOL> c . all_items <EOL> ] <EOL> def _get_collection_history ( self , state , passive = attributes . PASSIVE_OFF ) : <EOL> if self . key in state . committed_state : <EOL> c = state . committed_state [ self . key ] <EOL> else : <EOL> c = CollectionHistory ( self , state ) <EOL> if state . has_identity and ( passive & attributes . INIT_OK ) : <EOL> return CollectionHistory ( self , state , apply_to = c ) <EOL> else : <EOL> return c <EOL> def append ( self , state , dict_ , value , initiator , <EOL> passive = attributes . PASSIVE_OFF ) : <EOL> if initiator is not self : <EOL> self . fire_append_event ( state , dict_ , value , initiator ) <EOL> def remove ( self , state , dict_ , value , initiator , <EOL> passive = attributes . PASSIVE_OFF ) : <EOL> if initiator is not self : <EOL> self . fire_remove_event ( state , dict_ , value , initiator ) <EOL> def pop ( self , state , dict_ , value , initiator , <EOL> passive = attributes . PASSIVE_OFF ) : <EOL> self . remove ( state , dict_ , value , initiator , passive = passive ) <EOL> class AppenderMixin ( object ) : <EOL> query_class = None <EOL> def __init__ ( self , attr , state ) : <EOL> super ( AppenderMixin , self ) . __init__ ( attr . target_mapper , None ) <EOL> self . instance = instance = state . obj ( ) <EOL> self . attr = attr <EOL> mapper = object_mapper ( instance ) <EOL> prop = mapper . _props [ self . attr . key ] <EOL> self . _criterion = prop . compare ( <EOL> operators . eq , <EOL> instance , <EOL> value_is_parent = True , <EOL> alias_secondary = False ) <EOL> if self . attr . order_by : <EOL> self . _order_by = self . attr . order_by <EOL> def session ( self ) : <EOL> sess = object_session ( self . instance ) <EOL> if sess is not None and self . autoflush and sess . autoflush and self . instance in sess : <EOL> sess . flush ( ) <EOL> if not orm_util . has_identity ( self . instance ) : <EOL> return None <EOL> else : <EOL> return sess <EOL> session = property ( session , lambda s , x : None ) <EOL> def __iter__ ( self ) : <EOL> sess = self . session <EOL> if sess is None : <EOL> return iter ( self . attr . _get_collection_history ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . PASSIVE_NO_INITIALIZE ) . added_items ) <EOL> else : <EOL> return iter ( self . _clone ( sess ) ) <EOL> def __getitem__ ( self , index ) : <EOL> sess = self . session <EOL> if sess is None : <EOL> return self . attr . _get_collection_history ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . PASSIVE_NO_INITIALIZE ) . indexed ( index ) <EOL> else : <EOL> return self . _clone ( sess ) . __getitem__ ( index ) <EOL> def count ( self ) : <EOL> sess = self . session <EOL> if sess is None : <EOL> return len ( self . attr . _get_collection_history ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . PASSIVE_NO_INITIALIZE ) . added_items ) <EOL> else : <EOL> return self . _clone ( sess ) . count ( ) <EOL> def _clone ( self , sess = None ) : <EOL> instance = self . instance <EOL> if sess is None : <EOL> sess = object_session ( instance ) <EOL> if sess is None : <EOL> raise orm_exc . DetachedInstanceError ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % ( <EOL> orm_util . instance_str ( instance ) , self . attr . key ) ) <EOL> if self . query_class : <EOL> query = self . query_class ( self . attr . target_mapper , session = sess ) <EOL> else : <EOL> query = sess . query ( self . attr . target_mapper ) <EOL> query . _criterion = self . _criterion <EOL> query . _order_by = self . _order_by <EOL> return query <EOL> def extend ( self , iterator ) : <EOL> for item in iterator : <EOL> self . attr . append ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . instance_dict ( self . instance ) , item , None ) <EOL> def append ( self , item ) : <EOL> self . attr . append ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . instance_dict ( self . instance ) , item , None ) <EOL> def remove ( self , item ) : <EOL> self . attr . remove ( <EOL> attributes . instance_state ( self . instance ) , <EOL> attributes . instance_dict ( self . instance ) , item , None ) <EOL> class AppenderQuery ( AppenderMixin , Query ) : <EOL> """<STR_LIT>""" <EOL> def mixin_user_query ( cls ) : <EOL> """<STR_LIT>""" <EOL> name = '<STR_LIT>' + cls . __name__ <EOL> return type ( name , ( AppenderMixin , cls ) , { '<STR_LIT>' : cls } ) <EOL> class CollectionHistory ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , attr , state , apply_to = None ) : <EOL> if apply_to : <EOL> coll = AppenderQuery ( attr , state ) . autoflush ( False ) <EOL> self . unchanged_items = util . OrderedIdentitySet ( coll ) <EOL> self . added_items = apply_to . added_items <EOL> self . deleted_items = apply_to . deleted_items <EOL> self . _reconcile_collection = True <EOL> else : <EOL> self . deleted_items = util . OrderedIdentitySet ( ) <EOL> self . added_items = util . OrderedIdentitySet ( ) <EOL> self . unchanged_items = util . OrderedIdentitySet ( ) <EOL> self . _reconcile_collection = False <EOL> @ property <EOL> def added_plus_unchanged ( self ) : <EOL> return list ( self . added_items . union ( self . unchanged_items ) ) <EOL> @ property <EOL> def all_items ( self ) : <EOL> return list ( self . added_items . union ( <EOL> self . unchanged_items ) . union ( self . deleted_items ) ) <EOL> def as_history ( self ) : <EOL> if self . _reconcile_collection : <EOL> added = self . added_items . difference ( self . unchanged_items ) <EOL> deleted = self . deleted_items . intersection ( self . unchanged_items ) <EOL> unchanged = self . unchanged_items . difference ( deleted ) <EOL> else : <EOL> added , unchanged , deleted = self . added_items , self . unchanged_items , self . deleted_items <EOL> return attributes . History ( <EOL> list ( added ) , <EOL> list ( unchanged ) , <EOL> list ( deleted ) , <EOL> ) <EOL> def indexed ( self , index ) : <EOL> return list ( self . added_items ) [ index ] <EOL> def add_added ( self , value ) : <EOL> self . added_items . add ( value ) <EOL> def add_removed ( self , value ) : <EOL> if value in self . added_items : <EOL> self . added_items . remove ( value ) <EOL> else : <EOL> self . deleted_items . add ( value ) </s>
