From: Mike Bayer Date: Sat, 8 Nov 2008 21:00:15 +0000 (+0000) Subject: removed setup_instance() from the public API X-Git-Tag: rel_0_5rc4~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1901519fa7777ad84ed12827c192e57b7ef92139;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git removed setup_instance() from the public API of ClassManager, and made it a private method on _ClassInstrumentationAdapter. ClassManager's approach handles the default task with fewer function calls which chops off a few hundred calls from the pertinent profile tests. --- diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 36a532faa3..e80392d0cc 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -806,13 +806,13 @@ class InstanceState(object): self.manager = manager self.obj = weakref.ref(obj, self._cleanup) self.dict = obj.__dict__ - self.committed_state = {} self.modified = False self.callables = {} - self.parents = {} - self.pending = {} self.expired = False - + self.committed_state = {} + self.pending = {} + self.parents = {} + def detach(self): if self.session_id: del self.session_id @@ -862,9 +862,6 @@ class InstanceState(object): def get_impl(self, key): return self.manager.get_impl(key) - def get_inst(self, key): - return self.manager.get_inst(key) - def get_pending(self, key): if key not in self.pending: self.pending[key] = PendingCollection() @@ -933,7 +930,7 @@ class InstanceState(object): def __call__(self): """__call__ allows the InstanceState to act as a deferred callable for loading expired attributes, which is also - serializable. + serializable (picklable). """ unmodified = self.unmodified @@ -1052,9 +1049,10 @@ class InstanceState(object): if a value was not populated in state.dict. """ + self.committed_state = {} self.pending = {} - + # unexpire attributes which have loaded if self.expired_attributes: for key in self.expired_attributes.intersection(self.dict): @@ -1224,49 +1222,42 @@ class ClassManager(dict): def get_impl(self, key): return self[key].impl - get_inst = dict.__getitem__ - @property def attributes(self): return self.itervalues() @classmethod def deferred_scalar_loader(cls, state, keys): - """TODO""" + """Apply a scalar loader to the given state. + + Unimplemented by default, is patched + by the mapper. + + """ ## InstanceState management def new_instance(self, state=None): instance = self.class_.__new__(self.class_) - self.setup_instance(instance, state) + setattr(instance, self.STATE_ATTR, state or self.instance_state_factory(instance, self)) return instance - def setup_instance(self, instance, with_state=None): - """Register an InstanceState with an instance.""" - if self.has_state(instance): - state = self.state_of(instance) - if with_state: - assert state is with_state - return state - if with_state is None: - with_state = self.instance_state_factory(instance, self) - self.install_state(instance, with_state) - return with_state - - def install_state(self, instance, state): - setattr(instance, self.STATE_ATTR, state) - - def has_state(self, instance): - """True if an InstanceState is installed on the instance.""" - return bool(getattr(instance, self.STATE_ATTR, False)) - - def state_of(self, instance): - """Retrieve the InstanceState of an instance. + def _new_state_if_none(self, instance): + """Install a default InstanceState if none is present. - May raise KeyError or AttributeError if no state is available. + A private convenience method used by the __init__ decorator. + """ + if hasattr(instance, self.STATE_ATTR): + return False + else: + state = self.instance_state_factory(instance, self) + setattr(instance, self.STATE_ATTR, state) + return state + + def state_of(self, instance): return getattr(instance, self.STATE_ATTR) - + def state_getter(self): """Return a (instance) -> InstanceState callable. @@ -1274,18 +1265,12 @@ class ClassManager(dict): AttributeError if no InstanceState could be found for the instance. """ - return attrgetter(self.STATE_ATTR) - - def _new_state_if_none(self, instance): - """Install a default InstanceState if none is present. - - A private convenience method used by the __init__ decorator. - """ - if self.has_state(instance): - return False - else: - return self.setup_instance(instance) + return attrgetter(self.STATE_ATTR) + + def has_state(self, instance): + return hasattr(instance, self.STATE_ATTR) + def has_parent(self, state, key, optimistic=False): """TODO""" return self.get_impl(key).hasparent(state, optimistic=optimistic) @@ -1342,15 +1327,32 @@ class _ClassInstrumentationAdapter(ClassManager): else: return ClassManager.initialize_collection(self, key, state, factory) - def setup_instance(self, instance, state=None): + def new_instance(self, state=None): + instance = self.class_.__new__(self.class_) + self._setup_instance(instance, state) + return instance + + def _new_state_if_none(self, instance): + """Install a default InstanceState if none is present. + + A private convenience method used by the __init__ decorator. + """ + if self.has_state(instance): + return False + else: + return self._setup_instance(instance) + + def _setup_instance(self, instance, state=None): self._adapted.initialize_instance_dict(self.class_, instance) - state = ClassManager.setup_instance(self, instance, with_state=state) + + if state is None: + state = self.instance_state_factory(instance, self) + + # the given instance is assumed to have no state + self._adapted.install_state(self.class_, instance, state) state.dict = self._adapted.get_instance_dict(self.class_, instance) return state - def install_state(self, instance, state): - self._adapted.install_state(self.class_, instance, state) - def state_of(self, instance): if hasattr(self._adapted, 'state_of'): return self._adapted.state_of(self.class_, instance) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 2b860af370..63e144cd43 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -387,7 +387,7 @@ class PropertyLoader(StrategizedProperty): self.prop._create_joins(dest_polymorphic=True, dest_selectable=to_selectable, source_selectable=source_selectable) for k in kwargs: - crit = self.prop.mapper.class_manager.get_inst(k) == kwargs[k] + crit = self.prop.mapper.class_manager[k] == kwargs[k] if criterion is None: criterion = crit else: diff --git a/test/orm/extendedattr.py b/test/orm/extendedattr.py index 4914bbd709..6b2c04b71e 100644 --- a/test/orm/extendedattr.py +++ b/test/orm/extendedattr.py @@ -294,8 +294,8 @@ class UserDefinedExtensionTest(_base.ORMTest): attributes.register_attribute(Foo, "name", uselist=False, useobject=False) attributes.register_attribute(Foo, "bars", uselist=True, trackparent=True, useobject=True) - assert Foo.name == attributes.manager_of_class(Foo).get_inst('name') - assert Foo.bars == attributes.manager_of_class(Foo).get_inst('bars') + assert Foo.name == attributes.manager_of_class(Foo)['name'] + assert Foo.bars == attributes.manager_of_class(Foo)['bars'] def test_alternate_finders(self): """Ensure the generic finder front-end deals with edge cases.""" diff --git a/test/profiling/zoomark_orm.py b/test/profiling/zoomark_orm.py index 8350fbab4c..7af72b2586 100644 --- a/test/profiling/zoomark_orm.py +++ b/test/profiling/zoomark_orm.py @@ -290,7 +290,7 @@ class ZooMarkTest(TestBase): def test_profile_1_create_tables(self): self.test_baseline_1_create_tables() - @profiling.function_call_count(13636, {'2.4':12478}) + @profiling.function_call_count(12925, {'2.4':12478}) def test_profile_1a_populate(self): self.test_baseline_1a_populate() diff --git a/test/testlib/profiling.py b/test/testlib/profiling.py index 05b1435c37..89db330111 100644 --- a/test/testlib/profiling.py +++ b/test/testlib/profiling.py @@ -60,6 +60,7 @@ def profiled(target=None, **target_opts): stats.print_stats(limit) else: stats.print_stats() + #stats.print_callers() os.unlink(filename) return result return _function_named(profiled, fn.__name__)