def process_row(self, selectcontext, instance, row, identitykey, isnew): """Receive a row. Tell our mapper to look for a new object instance in the row, and attach it to a list on the parent instance. """ if self in selectcontext.recursion_stack: return try: # check for row processor row_processor = selectcontext.attributes[id(self)] except KeyError: # create a row processor function and cache it in the context row_processor = self._create_row_processor(selectcontext, row) selectcontext.attributes[id(self)] = row_processor if row_processor is not None: decorated_row = row_processor(row) else: # row_processor was None: degrade to a lazy loader if self._should_log_debug: self.logger.debug("degrade to lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) self.parent_property._get_strategy(LazyLoader).process_row(selectcontext, instance, row, identitykey, isnew) return # TODO: recursion check a speed hit...? try to get a "termination point" into the AliasedClauses # or EagerRowAdapter ? selectcontext.recursion_stack.add(self) try: if not self.uselist: if self._should_log_debug: self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) if isnew: # set a scalar object instance directly on the parent object, # bypassing SmartProperty event handlers. instance.__dict__[self.key] = self.mapper._instance(selectcontext, decorated_row, None) else: # call _instance on the row, even though the object has been created, # so that we further descend into properties self.mapper._instance(selectcontext, decorated_row, None) else: if isnew: if self._should_log_debug: self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) # call the SmartProperty's initialize() method to create a new, blank list l = getattr(instance.__class__, self.key).initialize(instance) # create an appender object which will add set-like semantics to the list appender = util.UniqueAppender(l.data) # store it in the "scratch" area, which is local to this load operation. selectcontext.attributes[(instance, self.key)] = appender result_list = selectcontext.attributes[(instance, self.key)] if self._should_log_debug: self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.mapper._instance(selectcontext, decorated_row, result_list) finally: selectcontext.recursion_stack.remove(self)
def execute(instance, row, isnew, **flags): decorated_row = row_decorator(row) if not self.uselist: if self._should_log_debug: self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) if isnew: # set a scalar object instance directly on the # parent object, bypassing InstrumentedAttribute # event handlers. # instance.__dict__[self.key] = self.mapper._instance(selectcontext, decorated_row, None) else: # call _instance on the row, even though the object has been created, # so that we further descend into properties self.mapper._instance(selectcontext, decorated_row, None) else: if isnew or self.key not in instance._state.appenders: # appender_key can be absent from selectcontext.attributes with isnew=False # when self-referential eager loading is used; the same instance may be present # in two distinct sets of result columns if self._should_log_debug: self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) collection = attributes.init_collection(instance, self.key) appender = util.UniqueAppender(collection, 'append_without_event') instance._state.appenders[self.key] = appender result_list = instance._state.appenders[self.key] if self._should_log_debug: self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.mapper._instance(selectcontext, decorated_row, result_list)
def execute(instance, row, isnew, **flags): decorated_row = row_decorator(row) selectcontext.stack.push_property(self.key) if not self.uselist: if self._should_log_debug: self.logger.debug( "eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) if isnew: # set a scalar object instance directly on the # parent object, bypassing InstrumentedAttribute # event handlers. # # FIXME: instead of... sessionlib.attribute_manager.set_raw_value( instance, self.key, self.select_mapper._instance( selectcontext, decorated_row, None)) # bypass and set directly: #instance.__dict__[self.key] = self.select_mapper._instance(selectcontext, decorated_row, None) else: # call _instance on the row, even though the object has been created, # so that we further descend into properties self.select_mapper._instance(selectcontext, decorated_row, None) else: if isnew: if self._should_log_debug: self.logger.debug( "initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) collection = sessionlib.attribute_manager.init_collection( instance, self.key) appender = util.UniqueAppender(collection, 'append_without_event') # store it in the "scratch" area, which is local to this load operation. selectcontext.attributes[(instance, self.key)] = appender result_list = selectcontext.attributes[(instance, self.key)] if self._should_log_debug: self.logger.debug( "eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.select_mapper._instance(selectcontext, decorated_row, result_list) selectcontext.stack.pop()
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: # new object instance being loaded from a result row if not self.is_default or len(selectcontext.options): self.logger.debug("set instance-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are not the primary manager for this attribute on this class - set up a per-instance lazyloader, # which will override the clareset_instance_attributess-level behavior self._init_instance_attribute(instance, callable_=self.setup_loader(instance, selectcontext.options)) else: self.logger.debug("set class-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are the primary manager for this attribute on this class - reset its per-instance attribute state, # so that the class-level lazy loader is executed when next referenced on this instance. # this usually is not needed unless the constructor of the object referenced the attribute before we got # to load data into it. sessionlib.attribute_manager.reset_instance_attribute(instance, self.key)
def __call__(self): if not mapper.has_identity(self.instance): return None localparent = mapper.object_mapper(self.instance, raiseerror=False) prop = localparent.get_property(self.key) strategy = prop._get_strategy(DeferredColumnLoader) if self.keys: toload = self.keys elif strategy.group: toload = [p.key for p in localparent.iterate_properties if isinstance(p.strategy, DeferredColumnLoader) and p.group==strategy.group] else: toload = [self.key] # narrow the keys down to just those which have no history group = [k for k in toload if k in self.instance._state.unmodified] if strategy._should_log_debug: strategy.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(self.instance, self.key), group and ','.join(group) or 'None')) session = sessionlib.object_session(self.instance) if session is None: raise exceptions.UnboundExecutionError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (self.instance.__class__, self.key)) query = session.query(localparent) if not self.optimizing_statement: ident = self.instance._instance_key[1] query._get(None, ident=ident, only_load_props=group, refresh_instance=self.instance._state) else: statement, params = self.optimizing_statement(self.instance) query.from_statement(statement).params(params)._get(None, only_load_props=group, refresh_instance=self.instance._state) return attributes.ATTR_WAS_SET
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug( "populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = row[self.columns[0]]
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug( "set deferred callable on %s" % mapperutil.attribute_str(instance, self.key)) instance._state.set_callable(self.key, self.setup_loader(instance))
def new_execute(instance, row, ispostselect, **flags): if not ispostselect: if self._should_log_debug: self.logger.debug( "initializing blank scalar/collection on %s" % mapperutil.attribute_str(instance, self.key)) self._init_instance_attribute(instance)
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug( "set deferred callable on %s" % mapperutil.attribute_str(instance, self.key)) sessionlib.attribute_manager.reset_instance_attribute( instance, self.key)
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: if self._should_log_debug: self.logger.debug( "populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = row[self.columns[0]]
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: if not self.is_default or len(selectcontext.options): if self._should_log_debug: self.logger.debug( "set instance-level no loader on %s" % mapperutil.attribute_str(instance, self.key)) self._init_instance_attribute(instance)
def new_execute(instance, row, ispostselect, **flags): if not ispostselect: if self._should_log_debug: self.logger.debug("set instance-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are not the primary manager for this attribute on this class - set up a per-instance lazyloader, # which will override the class-level behavior self._init_instance_attribute(instance, callable_=self.setup_loader(instance, selectcontext.options, selectcontext.query._current_path + selectcontext.path))
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug( "populating %s with %s/%s..." % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[ self.key] = self.parent_property.composite_class( *[row[c] for c in self.columns])
def lazyload(): if self._should_log_debug: self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str( instance, self.key), str(self.group))) if not mapper.has_identity(instance): return None try: pk = self.parent.pks_by_table[self.columns[0].table] except KeyError: pk = self.columns[0].table.primary_key clause = sql.and_() for primary_key in pk: attr = self.parent.get_attr_by_column(instance, primary_key) if not attr: return None clause.clauses.append(primary_key == attr) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) localparent = mapper.object_mapper(instance) if self.group is not None: groupcols = [ p for p in localparent.props.values() if isinstance(p.strategy, DeferredColumnLoader) and p.group == self.group ] result = session.execute( localparent, sql.select([g.columns[0] for g in groupcols], clause, use_labels=True), None) try: row = result.fetchone() for prop in groupcols: if prop is self: continue # set a scalar object instance directly on the object, # bypassing SmartProperty event handlers. sessionlib.attribute_manager.init_instance_attribute( instance, prop.key, uselist=False) instance.__dict__[prop.key] = row[prop.columns[0]] return row[self.columns[0]] finally: result.close() else: return session.scalar( localparent, sql.select([self.columns[0]], clause, use_labels=True), None)
def new_execute(instance, row, ispostselect, **flags): if not ispostselect: if self._should_log_debug: self.logger.debug("set class-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are the primary manager for this attribute on this class - reset its per-instance attribute state, # so that the class-level lazy loader is executed when next referenced on this instance. # this usually is not needed unless the constructor of the object referenced the attribute before we got # to load data into it. instance._state.reset(self.key)
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: # new object instance being loaded from a result row if not self.is_default or len(selectcontext.options): self.logger.debug("set instance-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are not the primary manager for this attribute on this class - set up a per-instance lazyloader, # which will override the clareset_instance_attributess-level behavior self._init_instance_attribute(instance, callable_=self.setup_loader( instance, selectcontext.options)) else: self.logger.debug("set class-level lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) # we are the primary manager for this attribute on this class - reset its per-instance attribute state, # so that the class-level lazy loader is executed when next referenced on this instance. # this usually is not needed unless the constructor of the object referenced the attribute before we got # to load data into it. sessionlib.attribute_manager.reset_instance_attribute( instance, self.key)
def lazyload(): if not mapper.has_identity(instance): return None if props is not None: group = props elif self.group is not None: group = [ p for p in localparent.iterate_properties if isinstance(p.strategy, DeferredColumnLoader) and p.group == self.group ] else: group = [self.parent_property] if self._should_log_debug: self.logger.debug( "deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), group and ','.join([p.key for p in group]) or 'None')) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError( "Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) if create_statement is None: (clause, param_map) = localparent._get_clause ident = instance._instance_key[1] params = {} for i, primary_key in enumerate(localparent.primary_key): params[param_map[primary_key].key] = ident[i] statement = sql.select([p.columns[0] for p in group], clause, from_obj=[localparent.mapped_table], use_labels=True) else: statement, params = create_statement() # TODO: have the "fetch of one row" operation go through the same channels as a query._get() # deferred load of several attributes should be a specialized case of a query refresh operation conn = session.connection(mapper=localparent, instance=instance) result = conn.execute(statement, params) try: row = result.fetchone() for prop in group: sessionlib.attribute_manager.set_committed_value( instance, prop.key, row[prop.columns[0]]) return attributes.ATTR_WAS_SET finally: result.close()
def lazyload(): if self._should_log_debug: self.logger.debug("deferred load %s group %s" % (mapperutil.attribute_str(instance, self.key), str(self.group))) if not mapper.has_identity(instance): return None try: pk = self.parent.pks_by_table[self.columns[0].table] except KeyError: pk = self.columns[0].table.primary_key clause = sql.and_() for primary_key in pk: attr = self.parent.get_attr_by_column(instance, primary_key) if not attr: return None clause.clauses.append(primary_key == attr) session = sessionlib.object_session(instance) if session is None: raise exceptions.InvalidRequestError("Parent instance %s is not bound to a Session; deferred load operation of attribute '%s' cannot proceed" % (instance.__class__, self.key)) localparent = mapper.object_mapper(instance) if self.group is not None: groupcols = [p for p in localparent.props.values() if isinstance(p.strategy, DeferredColumnLoader) and p.group==self.group] result = session.execute(localparent, sql.select([g.columns[0] for g in groupcols], clause, use_labels=True), None) try: row = result.fetchone() for prop in groupcols: if prop is self: continue # set a scalar object instance directly on the object, # bypassing SmartProperty event handlers. sessionlib.attribute_manager.init_instance_attribute(instance, prop.key, uselist=False) instance.__dict__[prop.key] = row[prop.columns[0]] return row[self.columns[0]] finally: result.close() else: return session.scalar(localparent, sql.select([self.columns[0]], clause, use_labels=True),None)
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: if not self.is_default or len(selectcontext.options): if self._should_log_debug: self.logger.debug("set instance-level no loader on %s" % mapperutil.attribute_str(instance, self.key)) self._init_instance_attribute(instance)
def process_row(self, selectcontext, instance, row, identitykey, isnew): if isnew: if self._should_log_debug: self.logger.debug("populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = row[self.columns[0]]
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug("set deferred callable on %s" % mapperutil.attribute_str(instance, self.key)) instance._state.set_callable(self.key, self.setup_loader(instance))
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug("populating %s with %s/%s" % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = row[self.columns[0]]
def new_execute(instance, row, **flags): if self._should_log_debug: self.logger.debug("populating %s with %s/%s..." % (mapperutil.attribute_str(instance, self.key), row.__class__.__name__, self.columns[0].key)) instance.__dict__[self.key] = self.parent_property.composite_class(*[row[c] for c in self.columns])
def new_execute(instance, row, ispostselect, **flags): if not ispostselect: if self._should_log_debug: self.logger.debug("initializing blank scalar/collection on %s" % mapperutil.attribute_str(instance, self.key)) self._init_instance_attribute(instance)
def process_row(self, selectcontext, instance, row, identitykey, isnew): """Receive a row. Tell our mapper to look for a new object instance in the row, and attach it to a list on the parent instance. """ if self in selectcontext.recursion_stack: return try: # check for row processor row_processor = selectcontext.attributes[id(self)] except KeyError: # create a row processor function and cache it in the context row_processor = self._create_row_processor(selectcontext, row) selectcontext.attributes[id(self)] = row_processor if row_processor is not None: decorated_row = row_processor(row) else: # row_processor was None: degrade to a lazy loader if self._should_log_debug: self.logger.debug("degrade to lazy loader on %s" % mapperutil.attribute_str(instance, self.key)) self.parent_property._get_strategy(LazyLoader).process_row( selectcontext, instance, row, identitykey, isnew) return # TODO: recursion check a speed hit...? try to get a "termination point" into the AliasedClauses # or EagerRowAdapter ? selectcontext.recursion_stack.add(self) try: if not self.uselist: if self._should_log_debug: self.logger.debug( "eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key)) if isnew: # set a scalar object instance directly on the parent object, # bypassing SmartProperty event handlers. instance.__dict__[self.key] = self.mapper._instance( selectcontext, decorated_row, None) else: # call _instance on the row, even though the object has been created, # so that we further descend into properties self.mapper._instance(selectcontext, decorated_row, None) else: if isnew: if self._should_log_debug: self.logger.debug( "initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key)) # call the SmartProperty's initialize() method to create a new, blank list l = getattr(instance.__class__, self.key).initialize(instance) # create an appender object which will add set-like semantics to the list appender = util.UniqueAppender(l.data) # store it in the "scratch" area, which is local to this load operation. selectcontext.attributes[(instance, self.key)] = appender result_list = selectcontext.attributes[(instance, self.key)] if self._should_log_debug: self.logger.debug( "eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key)) self.mapper._instance(selectcontext, decorated_row, result_list) finally: selectcontext.recursion_stack.remove(self)