Esempio n. 1
0
    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)
Esempio n. 2
0
            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)
Esempio n. 3
0
            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)
Esempio n. 4
0
            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()
Esempio n. 5
0
 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)
Esempio n. 6
0
    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
Esempio n. 7
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] = row[self.columns[0]]
Esempio n. 8
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))
Esempio n. 9
0
 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)
Esempio n. 10
0
    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
Esempio n. 11
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))
     sessionlib.attribute_manager.reset_instance_attribute(
         instance, self.key)
Esempio n. 12
0
 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]]
Esempio n. 13
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)
Esempio n. 14
0
 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))
Esempio n. 15
0
 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))
Esempio n. 16
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])
Esempio n. 17
0
        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)
Esempio n. 18
0
 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)
Esempio n. 19
0
 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)
Esempio n. 20
0
 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)
Esempio n. 21
0
        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()
Esempio n. 22
0
        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)
Esempio n. 23
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)
Esempio n. 24
0
 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]]
Esempio n. 25
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))
Esempio n. 26
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] = row[self.columns[0]]
Esempio n. 27
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])
Esempio n. 28
0
 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)
Esempio n. 29
0
    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)