PASSIVE_NO_RESULT = util.symbol('PASSIVE_NO_RESULT')
ATTR_WAS_SET = util.symbol('ATTR_WAS_SET')
+ATTR_EMPTY = util.symbol('ATTR_EMPTY')
NO_VALUE = util.symbol('NO_VALUE')
NEVER_SET = util.symbol('NEVER_SET')
self.impl = impl
self.comparator = comparator
self.parententity = parententity
-
+
manager = manager_of_class(class_)
# manager is None in the case of AliasedClass
if manager:
dispatch = event.dispatcher(events.AttributeEvents)
dispatch.dispatch_cls.active_history = False
+ @util.memoized_property
+ def _supports_population(self):
+ return self.impl.supports_population
+
def get_history(self, instance, **kwargs):
return self.impl.get_history(instance_state(instance),
instance_dict(instance), **kwargs)
def __get__(self, instance, owner):
if instance is None:
return self
- return self.impl.get(instance_state(instance),
- instance_dict(instance))
+
+ dict_ = instance_dict(instance)
+ if self._supports_population and self.key in dict_:
+ return dict_[self.key]
+ else:
+ return self.impl.get(instance_state(instance),dict_)
def create_proxied_attribute(descriptor):
"""Create an QueryableAttribute / user descriptor hybrid.
resulting value will be set as the new value for this attribute.
"""
- try:
+ if self.key in dict_:
return dict_[self.key]
- except KeyError:
- # if no history, check for lazy callables, etc.
- if state.committed_state.get(self.key, NEVER_SET) is NEVER_SET:
+ else:
+ # if history present, don't load
+ key = self.key
+ if key not in state.committed_state or \
+ state.committed_state[key] is NEVER_SET:
if passive is PASSIVE_NO_INITIALIZE:
return PASSIVE_NO_RESULT
- if self.key in state.callables:
- callable_ = state.callables[self.key]
- elif self.callable_ is not None:
- callable_ = self.callable_(state)
+ if key in state.callables:
+ callable_ = state.callables[key]
+ value = callable_(passive)
+ elif self.callable_:
+ value = self.callable_(state, passive)
else:
- callable_ = None
-
- if callable_ is not None:
- value = callable_(passive=passive)
- if value is PASSIVE_NO_RESULT:
- return value
- elif value is not ATTR_WAS_SET:
- return self.set_committed_value(state, dict_, value)
- else:
- if self.key not in dict_:
- return self.get(state, dict_, passive=passive)
- return dict_[self.key]
+ value = ATTR_EMPTY
+
+ if value is PASSIVE_NO_RESULT:
+ return value
+ elif value is ATTR_WAS_SET:
+ try:
+ return dict_[key]
+ except KeyError:
+ # TODO: no test coverage here.
+ raise KeyError(
+ "Deferred loader for attribute "
+ "%r failed to populate "
+ "correctly" % key)
+ elif value is not ATTR_EMPTY:
+ return self.set_committed_value(state, dict_, value)
# Return a new, empty value
return self.initialize(state, dict_)
dict.__setitem__(self, state.key, state)
self._manage_incoming_state(state)
-
+
def add(self, state):
- if state.key in self:
- if dict.__getitem__(self, state.key) is not state:
- raise AssertionError("A conflicting state is already "
- "present in the identity map for key %r"
- % (state.key, ))
- else:
- dict.__setitem__(self, state.key, state)
- self._manage_incoming_state(state)
-
+ key = state.key
+ # inline of self.__contains__
+ if dict.__contains__(self, key):
+ try:
+ existing_state = dict.__getitem__(self, key)
+ if existing_state is not state:
+ o = existing_state.obj()
+ if o is None:
+ o = existing_state._is_really_none()
+ if o is not None:
+ raise AssertionError("A conflicting state is already "
+ "present in the identity map for key %r"
+ % (key, ))
+ else:
+ return
+ except KeyError:
+ pass
+ dict.__setitem__(self, key, state)
+ self._manage_incoming_state(state)
+
def remove_key(self, key):
state = dict.__getitem__(self, key)
self.remove(state)
# TODO: no coverage here
return attributes.PASSIVE_NO_RESULT
try:
- state()
+ state(passive)
except orm_exc.ObjectDeletedError:
session._remove_newly_deleted(state)
return None
self.class_ = obj.__class__
self.manager = manager
self.obj = weakref.ref(obj, self._cleanup)
-
- @util.memoized_property
- def committed_state(self):
- return {}
+ self.callables = {}
+ self.committed_state = {}
@util.memoized_property
def parents(self):
def pending(self):
return {}
- @util.memoized_property
- def callables(self):
- return {}
-
@property
def has_identity(self):
return bool(self.key)
instance_dict.remove(self)
except AssertionError:
pass
+
# remove possible cycles
- self.__dict__.pop('callables', None)
- self.dispose()
-
+ self.callables.clear()
+
+ # inlining of self.dispose()
+ if self.session_id:
+ try:
+ del self.session_id
+ except AttributeError:
+ pass
+ del self.obj
+
def obj(self):
return None
else:
filter_deferred = False
- to_clear = (
- self.__dict__.get('pending', None),
- self.__dict__.get('committed_state', None),
- self.mutable_dict
- )
+ pending = self.__dict__.get('pending', None)
+ mutable_dict = self.mutable_dict
for key in attribute_names:
impl = self.manager[key].impl
self.callables[key] = self
dict_.pop(key, None)
- for d in to_clear:
- if d is not None:
- d.pop(key, None)
+ self.committed_state.pop(key, None)
+ if mutable_dict:
+ mutable_dict.pop(key, None)
+ if pending:
+ pending.pop(key, None)
- def __call__(self, **kw):
+ def __call__(self, passive):
"""__call__ allows the InstanceState to act as a deferred
callable for loading expired attributes, which is also
serializable (picklable).
"""
- if kw.get('passive') is PASSIVE_NO_FETCH:
+ if passive is PASSIVE_NO_FETCH:
return PASSIVE_NO_RESULT
toload = self.expired_attributes.\
if a value was not populated in state.dict.
"""
-
- self.__dict__.pop('committed_state', None)
- self.__dict__.pop('pending', None)
- if 'callables' in self.__dict__:
- callables = self.callables
- for key in list(callables):
- if key in dict_ and callables[key] is self:
- del callables[key]
+ self.committed_state.clear()
+ self.__dict__.pop('pending', None)
+ callables = self.callables
+ for key in list(callables):
+ if key in dict_ and callables[key] is self:
+ del callables[key]
+
for key in self.manager.mutable_attributes:
if key in dict_:
self.committed_state[key] = self.manager[key].impl.copy(dict_[key])
compare_function=self.columns[0].type.compare_values,
copy_function=self.columns[0].type.copy_value,
mutable_scalars=self.columns[0].type.is_mutable(),
- callable_=self._class_level_loader,
+ callable_=self._load_for_state,
expire_missing=False
)
setup_query(context, entity,
path, adapter, **kwargs)
- def _class_level_loader(self, state):
+ def _load_for_state(self, state, passive):
if not state.key:
- return None
-
- return LoadDeferredColumns(state, self.key)
-
-
-log.class_logger(DeferredColumnLoader)
-
-class LoadDeferredColumns(object):
- """serializable loader object used by DeferredColumnLoader"""
+ return attributes.ATTR_EMPTY
- __slots__ = 'state', 'key'
-
- def __init__(self, state, key):
- self.state = state
- self.key = key
-
- def __getstate__(self):
- return self.state, self.key
-
- def __setstate__(self, state):
- self.state, self.key = state
-
- def __call__(self, passive=False):
- state, key = self.state, self.key
-
if passive is attributes.PASSIVE_NO_FETCH:
return attributes.PASSIVE_NO_RESULT
-
- localparent = mapper._state_mapper(state)
+
+ prop = self.parent_property
+ localparent = state.manager.mapper
- prop = localparent._props[key]
- strategy = prop._get_strategy(DeferredColumnLoader)
-
- if strategy.group:
+ if self.group:
toload = [
p.key for p in
localparent.iterate_properties
if isinstance(p, StrategizedProperty) and
isinstance(p.strategy, DeferredColumnLoader) and
- p.group==strategy.group
+ p.group==self.group
]
else:
- toload = [key]
+ toload = [self.key]
# narrow the keys down to just those which have no history
group = [k for k in toload if k in state.unmodified]
raise orm_exc.DetachedInstanceError(
"Parent instance %s is not bound to a Session; "
"deferred load operation of attribute '%s' cannot proceed" %
- (mapperutil.state_str(state), key)
+ (mapperutil.state_str(state), self.key)
)
query = session.query(localparent)
query._load_on_ident(state.key,
only_load_props=group, refresh_state=state)
return attributes.ATTR_WAS_SET
+
+log.class_logger(DeferredColumnLoader)
+
+class LoadDeferredColumns(object):
+ """serializable loader object used by DeferredColumnLoader"""
+
+ def __init__(self, state, key):
+ self.state = state
+ self.key = key
+
+ def __call__(self, passive=False):
+ state, key = self.state, self.key
+
+ localparent = state.manager.mapper
+ prop = localparent._props[key]
+ strategy = prop._strategies[DeferredColumnLoader]
+ return strategy._load_for_state(state, passive)
class DeferredOption(StrategizedOption):
propagate_to_loaders = True
_register_attribute(self,
mapper,
useobject=True,
- callable_=self._class_level_loader,
+ callable_=self._load_for_state,
uselist = self.parent_property.uselist,
backref = self.parent_property.back_populates,
typecallable = self.parent_property.collection_class,
criterion = adapt_source(criterion)
return criterion
- def _class_level_loader(self, state):
+ def _load_for_state(self, state, passive):
if not state.key and \
(not self.parent_property.load_on_pending or not state.session_id):
- return None
-
- return LoadLazyAttribute(state, self.key)
-
- def create_row_processor(self, selectcontext, path, mapper, row, adapter):
- key = self.key
- if not self.is_class_level:
- def new_execute(state, dict_, row):
- # 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.
- # this currently only happens when using a
- # "lazyload" option on a "no load"
- # attribute - "eager" attributes always have a
- # class-level lazyloader installed.
- state.set_callable(dict_, key, LoadLazyAttribute(state, key))
- else:
- def new_execute(state, dict_, row):
- # 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 is needed in
- # populate_existing() types of scenarios to reset
- # any existing state.
- state.reset(dict_, key)
-
- return new_execute, None, None
-
- @classmethod
- def _create_lazy_clause(cls, prop, reverse_direction=False):
- binds = util.column_dict()
- lookup = util.column_dict()
- equated_columns = util.column_dict()
-
- if reverse_direction and prop.secondaryjoin is None:
- for l, r in prop.local_remote_pairs:
- _list = lookup.setdefault(r, [])
- _list.append((r, l))
- equated_columns[l] = r
- else:
- for l, r in prop.local_remote_pairs:
- _list = lookup.setdefault(l, [])
- _list.append((l, r))
- equated_columns[r] = l
-
- def col_to_bind(col):
- if col in lookup:
- for tobind, equated in lookup[col]:
- if equated in binds:
- return None
- if col not in binds:
- binds[col] = sql.bindparam(None, None, type_=col.type)
- return binds[col]
- return None
+ return attributes.ATTR_EMPTY
- lazywhere = prop.primaryjoin
-
- if prop.secondaryjoin is None or not reverse_direction:
- lazywhere = visitors.replacement_traverse(
- lazywhere, {}, col_to_bind)
-
- if prop.secondaryjoin is not None:
- secondaryjoin = prop.secondaryjoin
- if reverse_direction:
- secondaryjoin = visitors.replacement_traverse(
- secondaryjoin, {}, col_to_bind)
- lazywhere = sql.and_(lazywhere, secondaryjoin)
-
- bind_to_col = dict((binds[col].key, col) for col in binds)
-
- return lazywhere, bind_to_col, equated_columns
-
-log.class_logger(LazyLoader)
-
-class LoadLazyAttribute(object):
- """serializable loader object used by LazyLoader"""
-
- __slots__ = 'state', 'key'
-
- def __init__(self, state, key):
- self.state = state
- self.key = key
-
- def __getstate__(self):
- return self.state, self.key
-
- def __setstate__(self, state):
- self.state, self.key = state
-
- def __call__(self, passive=False):
- state, key = self.state, self.key
instance_mapper = state.manager.mapper
- prop = instance_mapper._props[key]
- prop_mapper = prop.mapper
- strategy = prop._strategies[LazyLoader]
+ prop = self.parent_property
+ key = self.key
+ prop_mapper = self.mapper
pending = not state.key
if (
passive is attributes.PASSIVE_NO_FETCH and
- not strategy.use_get
+ not self.use_get
) or (
passive is attributes.PASSIVE_ONLY_PERSISTENT and
pending
# if we have a simple primary key load, check the
# identity map without generating a Query at all
- if strategy.use_get:
+ if self.use_get:
if session._flushing:
get_attr = instance_mapper._get_committed_state_attr_by_column
else:
get_attr(
state,
state.dict,
- strategy._equated_columns[pk],
+ self._equated_columns[pk],
passive=passive)
for pk in prop_mapper.primary_key
]
if state.load_options:
q = q._conditional_options(*state.load_options)
- if strategy.use_get:
+ if self.use_get:
return q._load_on_ident(ident_key)
if prop.order_by:
not isinstance(rev.strategy, LazyLoader):
q = q.options(EagerLazyOption((rev.key,), lazy='select'))
- lazy_clause = strategy.lazy_clause(state)
+ lazy_clause = self.lazy_clause(state)
if pending:
bind_values = sql_util.bind_values(lazy_clause)
q = q.filter(lazy_clause)
result = q.all()
- if strategy.uselist:
+ if self.uselist:
return result
else:
l = len(result)
else:
return None
+ def create_row_processor(self, selectcontext, path, mapper, row, adapter):
+ key = self.key
+ if not self.is_class_level:
+ def new_execute(state, dict_, row):
+ # 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.
+ # this currently only happens when using a
+ # "lazyload" option on a "no load"
+ # attribute - "eager" attributes always have a
+ # class-level lazyloader installed.
+ state.set_callable(dict_, key, LoadLazyAttribute(state, key))
+ else:
+ def new_execute(state, dict_, row):
+ # 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 is needed in
+ # populate_existing() types of scenarios to reset
+ # any existing state.
+ state.reset(dict_, key)
+
+ return new_execute, None, None
+
+ @classmethod
+ def _create_lazy_clause(cls, prop, reverse_direction=False):
+ binds = util.column_dict()
+ lookup = util.column_dict()
+ equated_columns = util.column_dict()
+
+ if reverse_direction and prop.secondaryjoin is None:
+ for l, r in prop.local_remote_pairs:
+ _list = lookup.setdefault(r, [])
+ _list.append((r, l))
+ equated_columns[l] = r
+ else:
+ for l, r in prop.local_remote_pairs:
+ _list = lookup.setdefault(l, [])
+ _list.append((l, r))
+ equated_columns[r] = l
+
+ def col_to_bind(col):
+ if col in lookup:
+ for tobind, equated in lookup[col]:
+ if equated in binds:
+ return None
+ if col not in binds:
+ binds[col] = sql.bindparam(None, None, type_=col.type)
+ return binds[col]
+ return None
+
+ lazywhere = prop.primaryjoin
+
+ if prop.secondaryjoin is None or not reverse_direction:
+ lazywhere = visitors.replacement_traverse(
+ lazywhere, {}, col_to_bind)
+
+ if prop.secondaryjoin is not None:
+ secondaryjoin = prop.secondaryjoin
+ if reverse_direction:
+ secondaryjoin = visitors.replacement_traverse(
+ secondaryjoin, {}, col_to_bind)
+ lazywhere = sql.and_(lazywhere, secondaryjoin)
+
+ bind_to_col = dict((binds[col].key, col) for col in binds)
+
+ return lazywhere, bind_to_col, equated_columns
+
+log.class_logger(LazyLoader)
+
+class LoadLazyAttribute(object):
+ """serializable loader object used by LazyLoader"""
+
+ def __init__(self, state, key):
+ self.state = state
+ self.key = key
+
+ def __call__(self, passive=False):
+ state, key = self.state, self.key
+ instance_mapper = state.manager.mapper
+ prop = instance_mapper._props[key]
+ strategy = prop._strategies[LazyLoader]
+
+ return strategy._load_for_state(state, passive)
+
+
class ImmediateLoader(AbstractRelationshipLoader):
def init_class_attribute(self, mapper):
self.parent_property.\
parents = sess.query(Parent).all()
children = sess.query(Child).all()
- @profiling.function_call_count(23979, {'2.5':28974, '3':25978})
+ @profiling.function_call_count(17987, {'3':20978})
def go():
for p in parents:
p.child
def test_pickleness(self):
instrumentation.register_class(MyTest)
instrumentation.register_class(MyTest2)
- attributes.register_attribute(MyTest, 'user_id', uselist=False, useobject=False)
- attributes.register_attribute(MyTest, 'user_name', uselist=False, useobject=False)
- attributes.register_attribute(MyTest, 'email_address', uselist=False, useobject=False)
- attributes.register_attribute(MyTest, 'some_mutable_data', mutable_scalars=True, copy_function=list, compare_function=cmp, uselist=False, useobject=False)
- attributes.register_attribute(MyTest2, 'a', uselist=False, useobject=False)
- attributes.register_attribute(MyTest2, 'b', uselist=False, useobject=False)
+ attributes.register_attribute(MyTest, 'user_id', uselist=False,
+ useobject=False)
+ attributes.register_attribute(MyTest, 'user_name',
+ uselist=False, useobject=False)
+ attributes.register_attribute(MyTest, 'email_address',
+ uselist=False, useobject=False)
+ attributes.register_attribute(MyTest, 'some_mutable_data',
+ mutable_scalars=True, copy_function=list,
+ compare_function=cmp, uselist=False, useobject=False)
+ attributes.register_attribute(MyTest2, 'a', uselist=False,
+ useobject=False)
+ attributes.register_attribute(MyTest2, 'b', uselist=False,
+ useobject=False)
+
# shouldnt be pickling callables at the class level
- def somecallable(*args, **kw):
+
+ def somecallable(state, passive):
return None
- attributes.register_attribute(MyTest, "mt2", uselist = True, trackparent=True, callable_=somecallable, useobject=True)
+
+ attributes.register_attribute(MyTest, 'mt2', uselist=True,
+ trackparent=True, callable_=somecallable,
+ useobject=True)
o = MyTest()
o.mt2.append(MyTest2())
b1, b2, b3, b4 = Bar(id='b1'), Bar(id='b2'), Bar(id='b3'), Bar(id='b4')
- def loadcollection(**kw):
- if kw.get('passive') is attributes.PASSIVE_NO_FETCH:
+ def loadcollection(state, passive):
+ if passive is attributes.PASSIVE_NO_FETCH:
return attributes.PASSIVE_NO_RESULT
return [b1, b2]
- def loadscalar(**kw):
- if kw.get('passive') is attributes.PASSIVE_NO_FETCH:
+ def loadscalar(state, passive):
+ if passive is attributes.PASSIVE_NO_FETCH:
return attributes.PASSIVE_NO_RESULT
return b2
attributes.register_attribute(Foo, 'bars',
uselist=True,
useobject=True,
- callable_=lambda o:loadcollection,
+ callable_=loadcollection,
extension=[ReceiveEvents('bars')])
attributes.register_attribute(Foo, 'bar',
uselist=False,
useobject=True,
- callable_=lambda o:loadscalar,
+ callable_=loadscalar,
extension=[ReceiveEvents('bar')])
attributes.register_attribute(Foo, 'scalar',
instrumentation.register_class(Bar)
bar1, bar2, bar3 = [Bar(id=1), Bar(id=2), Bar(id=3)]
- def func1(**kw):
- if kw.get('passive') is attributes.PASSIVE_NO_FETCH:
+ def func1(state, passive):
+ if passive is attributes.PASSIVE_NO_FETCH:
return attributes.PASSIVE_NO_RESULT
return [bar1, bar2, bar3]
- attributes.register_attribute(Foo, 'bars', uselist=True, callable_=lambda o:func1, useobject=True, extension=[ReceiveEvents()])
- attributes.register_attribute(Bar, 'foos', uselist=True, useobject=True, backref="bars")
+ attributes.register_attribute(Foo, 'bars', uselist=True,
+ callable_=func1, useobject=True,
+ extension=[ReceiveEvents()])
+ attributes.register_attribute(Bar, 'foos', uselist=True,
+ useobject=True, backref='bars')
x = Foo()
assert_raises(AssertionError, Bar(id=4).foos.append, x)
b = Blog()
p1 = Post()
attributes.instance_state(b).set_callable(attributes.instance_dict(b),
- 'posts', lambda **kw:[p1])
+ 'posts', lambda passive:[p1])
attributes.instance_state(p1).set_callable(attributes.instance_dict(p1),
- 'blog', lambda **kw:b)
+ 'blog', lambda passive:b)
p1, attributes.instance_state(b).commit_all(attributes.instance_dict(b))
# no orphans (called before the lazy loaders fire off)
instrumentation.register_class(Foo)
instrumentation.register_class(Bar)
- def func1(**kw):
+ def func1(state, passive):
return "this is the foo attr"
- def func2(**kw):
+ def func2(state, passive):
return "this is the bar attr"
- def func3(**kw):
+ def func3(state, passive):
return "this is the shared attr"
attributes.register_attribute(Foo, 'element', uselist=False,
- callable_=lambda o:func1, useobject=True)
+ callable_=func1, useobject=True)
attributes.register_attribute(Foo, 'element2', uselist=False,
- callable_=lambda o:func3, useobject=True)
+ callable_=func3, useobject=True)
attributes.register_attribute(Bar, 'element', uselist=False,
- callable_=lambda o:func2, useobject=True)
+ callable_=func2, useobject=True)
x = Foo()
y = Bar()
instrumentation.register_class(Bar)
bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)]
- def func1(**kw):
+ def func1(state, passive):
return "this is func 1"
- def func2(**kw):
+ def func2(state, passive):
return [bar1, bar2, bar3]
- attributes.register_attribute(Foo, 'col1', uselist=False, callable_=lambda o:func1, useobject=True)
- attributes.register_attribute(Foo, 'col2', uselist=True, callable_=lambda o:func2, useobject=True)
- attributes.register_attribute(Bar, 'id', uselist=False, useobject=True)
+ attributes.register_attribute(Foo, 'col1', uselist=False,
+ callable_=func1, useobject=True)
+ attributes.register_attribute(Foo, 'col2', uselist=True,
+ callable_=func2, useobject=True)
+ attributes.register_attribute(Bar, 'id', uselist=False,
+ useobject=True)
x = Foo()
attributes.instance_state(x).commit_all(attributes.instance_dict(x))
# and this condition changes.
assert c1 in p1.children
-
-
-
class PendingBackrefTest(_base.ORMTest):
def setup(self):
global Post, Blog, called, lazy_load
called = [0]
lazy_load = []
- def lazy_posts(instance):
- def load(**kw):
- if kw['passive'] is not attributes.PASSIVE_NO_FETCH:
- called[0] += 1
- return lazy_load
- else:
- return attributes.PASSIVE_NO_RESULT
- return load
+ def lazy_posts(state, passive):
+ if passive is not attributes.PASSIVE_NO_FETCH:
+ called[0] += 1
+ return lazy_load
+ else:
+ return attributes.PASSIVE_NO_RESULT
instrumentation.register_class(Post)
instrumentation.register_class(Blog)
- attributes.register_attribute(Post, 'blog', uselist=False, backref='posts', trackparent=True, useobject=True)
- attributes.register_attribute(Blog, 'posts', uselist=True, backref='blog', callable_=lazy_posts, trackparent=True, useobject=True)
+ attributes.register_attribute(Post, 'blog', uselist=False,
+ backref='posts', trackparent=True, useobject=True)
+ attributes.register_attribute(Blog, 'posts', uselist=True,
+ backref='blog', callable_=lazy_posts, trackparent=True,
+ useobject=True)
def test_lazy_add(self):
global lazy_load
pass
lazy_load = []
- def lazyload(instance):
- def load(**kw):
- return lazy_load
- return load
+ def lazyload(state, passive):
+ return lazy_load
instrumentation.register_class(Foo)
instrumentation.register_class(Bar)
- attributes.register_attribute(Foo, 'bars', uselist=True, backref='foo', trackparent=True, callable_=lazyload, useobject=True)
- attributes.register_attribute(Bar, 'foo', uselist=False, backref='bars', trackparent=True, useobject=True)
+ attributes.register_attribute(Foo, 'bars', uselist=True,
+ backref='foo', trackparent=True, callable_=lazyload,
+ useobject=True)
+ attributes.register_attribute(Bar, 'foo', uselist=False,
+ backref='bars', trackparent=True, useobject=True)
bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)]
lazy_load = [bar1, bar2, bar3]
pass
lazy_load = []
- def lazyload(instance):
- def load(**kw):
- return lazy_load
- return load
+ def lazyload(state, passive):
+ return lazy_load
instrumentation.register_class(Foo)
instrumentation.register_class(Bar)
- attributes.register_attribute(Foo, 'bars', uselist=True, callable_=lazyload, trackparent=True, useobject=True)
+ attributes.register_attribute(Foo, 'bars', uselist=True,
+ callable_=lazyload, trackparent=True, useobject=True)
bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)]
lazy_load = [bar1, bar2, bar3]
pass
lazy_load = None
- def lazyload(instance):
- def load(**kw):
- return lazy_load
- return load
+ def lazyload(state, passive):
+ return lazy_load
instrumentation.register_class(Foo)
- attributes.register_attribute(Foo, 'bar', uselist=False, callable_=lazyload, useobject=False)
- lazy_load = "hi"
+ attributes.register_attribute(Foo, 'bar', uselist=False,
+ callable_=lazyload, useobject=False)
+ lazy_load = 'hi'
# with scalar non-object and active_history=False, the lazy callable is only executed on gets, not history
# operations
pass
lazy_load = None
- def lazyload(instance):
- def load(**kw):
- return lazy_load
- return load
+ def lazyload(state, passive):
+ return lazy_load
instrumentation.register_class(Foo)
- attributes.register_attribute(Foo, 'bar', uselist=False, callable_=lazyload, useobject=False, active_history=True)
- lazy_load = "hi"
+ attributes.register_attribute(Foo, 'bar', uselist=False,
+ callable_=lazyload, useobject=False,
+ active_history=True)
+ lazy_load = 'hi'
# active_history=True means the lazy callable is executed on set as well as get,
# causing the old value to appear in the history
pass
lazy_load = None
- def lazyload(instance):
- def load(**kw):
- return lazy_load
- return load
+ def lazyload(state, passive):
+ return lazy_load
instrumentation.register_class(Foo)
instrumentation.register_class(Bar)
- attributes.register_attribute(Foo, 'bar', uselist=False, callable_=lazyload, trackparent=True, useobject=True)
+ attributes.register_attribute(Foo, 'bar', uselist=False,
+ callable_=lazyload, trackparent=True, useobject=True)
bar1, bar2 = [Bar(id=1), Bar(id=2)]
lazy_load = bar1
instrumentation.register_class(Foo)
instrumentation.register_class(Bar)
- def func1(**kw):
- print "func1"
+ def func1(state, passive):
return "this is the foo attr"
- def func2(**kw):
- print "func2"
+ def func2(state, passive):
return "this is the bar attr"
- def func3(**kw):
- print "func3"
+ def func3(state, passive):
return "this is the shared attr"
- attributes.register_attribute(Foo, 'element', uselist=False, callable_=lambda o:func1, useobject=True)
- attributes.register_attribute(Foo, 'element2', uselist=False, callable_=lambda o:func3, useobject=True)
- attributes.register_attribute(Bar, 'element', uselist=False, callable_=lambda o:func2, useobject=True)
+ attributes.register_attribute(Foo, 'element',
+ uselist=False, callable_=func1,
+ useobject=True)
+ attributes.register_attribute(Foo, 'element2',
+ uselist=False, callable_=func3,
+ useobject=True)
+ attributes.register_attribute(Bar, 'element',
+ uselist=False, callable_=func2,
+ useobject=True)
x = Foo()
y = Bar()
instrumentation.register_class(Post)
instrumentation.register_class(Blog)
- attributes.register_attribute(Post, 'blog', uselist=False, backref='posts', trackparent=True, useobject=True)
- attributes.register_attribute(Blog, 'posts', uselist=True, backref='blog', trackparent=True, useobject=True)
+ attributes.register_attribute(Post, 'blog', uselist=False,
+ backref='posts', trackparent=True, useobject=True)
+ attributes.register_attribute(Blog, 'posts', uselist=True,
+ backref='blog', trackparent=True, useobject=True)
b = Blog()
(p1, p2, p3) = (Post(), Post(), Post())
b.posts.append(p1)