def append_event(self, event, obj, value): """called by InstrumentedList when an item is appended""" obj._state['modified'] = True if self.trackparent and value is not None: self.sethasparent(value, True) for ext in self.extensions: ext.append(event or self, obj, value) def remove_event(self, event, obj, value): """called by InstrumentedList when an item is removed""" obj._state['modified'] = True if self.trackparent and value is not None: self.sethasparent(value, False) for ext in self.extensions: ext.delete(event or self, obj, value) InstrumentedAttribute.logger = logging.class_logger(InstrumentedAttribute) class InstrumentedList(object): """instruments a list-based attribute. all mutator operations (i.e. append, remove, etc.) will fire off events to the InstrumentedAttribute that manages the object's attribute. those events in turn trigger things like backref operations and whatever is implemented by do_list_value_changed on InstrumentedAttribute. note that this list does a lot less than earlier versions of SA list-based attributes, which used HistoryArraySet. this list wrapper does *not* maintain setlike semantics, meaning you can add as many duplicates as you want (which can break a lot of SQL), and also does not do anything related to history tracking. Please see ticket #213 for information on the future of this class, where it will be broken out into more collection-specific subtypes.""" def __init__(self, attr, obj, data, init=True): self.attr = attr # this weakref is to prevent circular references between the parent object
pass def process_query_context(self, context): self.process_query_property(context, self._get_property(context)) def process_selection_context(self, context): self.process_selection_property(context, self._get_property(context)) def _get_property(self, context): try: prop = self.__prop except AttributeError: mapper = context.mapper for token in self.key.split('.'): prop = mapper.props[token] mapper = getattr(prop, 'mapper', None) self.__prop = prop return prop PropertyOption.logger = logging.class_logger(PropertyOption) class StrategizedOption(PropertyOption): """a MapperOption that affects which LoaderStrategy will be used for an operation by a StrategizedProperty.""" def process_query_property(self, context, property): self.logger.debug("applying option to QueryContext, property key '%s'" % self.key) context.attributes[(LoaderStrategy, property)] = self.get_strategy_class() def process_selection_property(self, context, property): self.logger.debug("applying option to SelectionContext, property key '%s'" % self.key) context.attributes[(LoaderStrategy, property)] = self.get_strategy_class() def get_strategy_class(self): raise NotImplementedError() class LoaderStrategy(object):
uselist=False, copy_function=coltype.copy_value, compare_function=coltype.compare_values, mutable_scalars=self.columns[0].type.is_mutable()) 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]] ColumnLoader.logger = logging.class_logger(ColumnLoader) class DeferredColumnLoader(LoaderStrategy): """describes an object attribute that corresponds to a table column, which also will "lazy load" its value from the table. this is per-column lazy loading.""" def init(self): super(DeferredColumnLoader, self).init() self.columns = self.parent_property.columns self.group = self.parent_property.group self._should_log_debug = logging.is_debug_enabled(self.logger) def init_class_attribute(self): self.logger.info("register managed attribute %s on class %s" % (self.key, self.parent.class_.__name__)) sessionlib.attribute_manager.register_attribute(
value = None else: value = self.source_mapper.get_attr_by_column( source, self.source_column) if isinstance(dest, dict): dest[self.dest_column.key] = value else: if clearkeys and self.dest_primary_key(): raise exceptions.AssertionError( "Dependency rule tried to blank-out primary key column '%s' on instance '%s'" % (str(self.dest_column), mapperutil.instance_str(dest))) if logging.is_debug_enabled(self.logger): self.logger.debug( "execute() instances: %s(%s)->%s(%s) ('%s')" % (mapperutil.instance_str(source), str(self.source_column), mapperutil.instance_str(dest), str( self.dest_column), value)) self.dest_mapper.set_attr_by_column(dest, self.dest_column, value) SyncRule.logger = logging.class_logger(SyncRule) class BinaryVisitor(sql.ClauseVisitor): def __init__(self, func): self.func = func def visit_binary(self, binary): self.func(binary)
# TODO: this should be done at the SQL level not the mapper level if kwargs.get('distinct', False) and order_by: [statement.append_column(c) for c in util.to_list(order_by)] context.statement = statement # give all the attached properties a chance to modify the query for value in self.mapper.props.values(): value.setup(context) return statement def __log_debug(self, msg): self.logger.debug(msg) Query.logger = logging.class_logger(Query) class QueryContext(OperationContext): """created within the Query.compile() method to store and share state among all the Mappers and MapperProperty objects used in a query construction.""" def __init__(self, query, kwargs): self.query = query self.order_by = kwargs.pop('order_by', False) self.from_obj = kwargs.pop('from_obj', []) self.lockmode = kwargs.pop('lockmode', query.lockmode) self.distinct = kwargs.pop('distinct', False) self.limit = kwargs.pop('limit', None) self.offset = kwargs.pop('offset', None) self.eager_loaders = util.Set([x for x in query.mapper._eager_loaders]) self.statement = None