summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-03-21 04:38:54 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-03-21 04:38:54 +0000
commite5d2ac6a11f932f01281b8495494e28c1233856a (patch)
tree59d40351ac80a34674c10501480093dcfe48b2b7 /lib/sqlalchemy
parent85bc3613e87001369bbcd68045dd5fa77acb0cbd (diff)
downloadsqlalchemy-e5d2ac6a11f932f01281b8495494e28c1233856a.tar.gz
a few changes to attributes.py to allow faster initialization of object attributes on new objects
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/attributes.py34
-rw-r--r--lib/sqlalchemy/mapping/mapper.py4
-rw-r--r--lib/sqlalchemy/mapping/properties.py6
3 files changed, 36 insertions, 8 deletions
diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py
index b03ead1c2..437baeea8 100644
--- a/lib/sqlalchemy/attributes.py
+++ b/lib/sqlalchemy/attributes.py
@@ -72,6 +72,8 @@ class PropHistory(object):
self.key = key
self.orig = PropHistory.NONE
self.extension = extension
+ def plain_init(self, *args):
+ pass
def gethistory(self, *args, **kwargs):
return self
def clear(self):
@@ -152,7 +154,8 @@ class ListElement(util.HistoryArraySet):
obj.__dict__[key] = []
util.HistoryArraySet.__init__(self, list_, readonly=kwargs.get('readonly', False))
-
+ def plain_init(self, *args):
+ pass
def gethistory(self, *args, **kwargs):
return self
def list_value_changed(self, obj, key, item, listval, isdelete):
@@ -194,6 +197,14 @@ class CallableProp(object):
self.live = live
self.kwargs = kwargs
+ def plain_init(self, attrhist):
+ if not self.uselist:
+ p = PropHistory(self.obj, self.key, **self.kwargs)
+ self.obj.__dict__[self.key] = None
+ else:
+ p = self.manager.create_list(self.obj, self.key, None, readonly=self.live, **self.kwargs)
+ attrhist[self.key] = p
+
def gethistory(self, passive=False, *args, **kwargs):
if not self.uselist:
if self.obj.__dict__.get(self.key, None) is None:
@@ -337,12 +348,21 @@ class AttributeManager(object):
self.attribute_history(obj)[key] = p
return p
+ def init_attr(self, obj):
+ """sets up the _managed_attributes dictionary on an object. this happens anyway regardless
+ of this method being called, but saves on KeyErrors being thrown in get_history()."""
+ d = {}
+ obj.__dict__['_managed_attributes'] = d
+ cls_managed = self.class_managed(obj.__class__)
+ for value in cls_managed.values():
+ value(obj, d).plain_init(d)
+
def get_history(self, obj, key, passive=False, **kwargs):
"""returns the "history" container for the given attribute on the given object.
If the container does not exist, it will be created based on the class-level
history container definition."""
try:
- return self.attribute_history(obj)[key].gethistory(passive=passive, **kwargs)
+ return obj.__dict__['_managed_attributes'][key].gethistory(passive=passive, **kwargs)
except KeyError, e:
return self.class_managed(obj.__class__)[key](obj, **kwargs).gethistory(passive=passive, **kwargs)
@@ -351,14 +371,14 @@ class AttributeManager(object):
this dictionary is attached to the object via the attribute '_managed_attributes'.
If the dictionary does not exist, it will be created."""
try:
- attr = obj.__dict__['_managed_attributes']
+ return obj.__dict__['_managed_attributes']
except KeyError:
trigger = obj.__dict__.pop('_managed_trigger', None)
if trigger:
trigger()
attr = {}
obj.__dict__['_managed_attributes'] = attr
- return attr
+ return attr
def trigger_history(self, obj, callable):
try:
@@ -424,13 +444,15 @@ class AttributeManager(object):
the new object instance as an argument to create the new history container.
Extra keyword arguments can be sent which
will be passed along to newly created history containers."""
- def createprop(obj):
+ def createprop(obj, attrhist=None):
if callable_ is not None:
func = callable_(obj)
else:
func = None
p = self.create_history_container(obj, key, uselist, callable_=func, **kwargs)
- self.attribute_history(obj)[key] = p
+ if attrhist is None:
+ attrhist = self.attribute_history(obj)
+ attrhist[key] = p
return p
self.class_managed(class_)[key] = createprop
diff --git a/lib/sqlalchemy/mapping/mapper.py b/lib/sqlalchemy/mapping/mapper.py
index 32271aff5..a46064e6f 100644
--- a/lib/sqlalchemy/mapping/mapper.py
+++ b/lib/sqlalchemy/mapping/mapper.py
@@ -239,6 +239,10 @@ class Mapper(object):
if not self.class_.__dict__.has_key('_mapper'):
oldinit = self.class_.__init__
def init(self, *args, **kwargs):
+ # this gets the AttributeManager to do some pre-initialization,
+ # in order to save on KeyErrors later on
+ objectstore.global_attributes.init_attr(self)
+
nohist = kwargs.pop('_mapper_nohistory', False)
session = kwargs.pop('_sa_session', objectstore.get_session())
if not nohist:
diff --git a/lib/sqlalchemy/mapping/properties.py b/lib/sqlalchemy/mapping/properties.py
index 4d04997a6..ff3d1548c 100644
--- a/lib/sqlalchemy/mapping/properties.py
+++ b/lib/sqlalchemy/mapping/properties.py
@@ -714,6 +714,9 @@ class EagerLoader(PropertyLoader):
#print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.table.name
finally:
del recursion_stack[self.parent.table]
+
+ self._row_decorator = self._create_decorator_row()
+
self._eager_chained = True
def _aliasize_orderby(self, orderby, copy=True):
@@ -758,7 +761,6 @@ class EagerLoader(PropertyLoader):
for key, value in self.mapper.props.iteritems():
value.setup(key, statement, eagertable=self.eagertarget)
- self._decorator_row = self._create_decorator_row()
def execute(self, instance, row, identitykey, imap, isnew):
"""receive a row. tell our mapper to look for a new object instance in the row, and attach
@@ -809,7 +811,7 @@ class EagerLoader(PropertyLoader):
# (neither do any MapperExtensions). The row is keyed off the Column object
# (which is what mappers use) as well as its "label" (which might be what
# user-defined code is using)
- row = self._decorator_row(row)
+ row = self._row_decorator(row)
return self.mapper._instance(row, imap, result_list)
class GenericOption(MapperOption):