summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-11-08 21:00:15 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-11-08 21:00:15 +0000
commit1901519fa7777ad84ed12827c192e57b7ef92139 (patch)
treeb5108e243532c034840b28f0ee5444b5082a1ac8
parent17980ba83c9e492f156e9c027ce62990e5f9d6fa (diff)
downloadsqlalchemy-1901519fa7777ad84ed12827c192e57b7ef92139.tar.gz
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.
-rw-r--r--lib/sqlalchemy/orm/attributes.py106
-rw-r--r--lib/sqlalchemy/orm/properties.py2
-rw-r--r--test/orm/extendedattr.py4
-rw-r--r--test/profiling/zoomark_orm.py2
-rw-r--r--test/testlib/profiling.py1
5 files changed, 59 insertions, 56 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index 36a532faa..e80392d0c 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 2b860af37..63e144cd4 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 4914bbd70..6b2c04b71 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 8350fbab4..7af72b258 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 05b1435c3..89db33011 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__)