added 'import_instance' to properly deal with out-of-imap objects,

added assertion upon commit that all mapped objects are properly present in the identity map
This commit is contained in:
Mike Bayer
2006-01-08 01:34:13 +00:00
parent a4477a53bb
commit 77a11675bb
+39 -2
View File
@@ -87,6 +87,31 @@ def has_instance(instance):
def instance_key(instance):
"""returns the IdentityMap key for the given instance"""
return object_mapper(instance).instance_key(instance)
def import_instance(instance):
"""places the given instance in the current thread's unit of work context,
either in the current IdentityMap or marked as "new". Returns either the object
or the current corresponding version in the Identity Map.
this method should be used for any object instance that is coming from a serialized
storage, from another thread (assuming the regular threaded unit of work model), or any
case where the instance was loaded/created corresponding to a different base unitofwork
than the current one."""
if instance is None:
return None
key = getattr(instance, '_instance_key', None)
mapper = object_mapper(instance)
key = (key[0], repr(mapper.table), key[2])
u = uow()
if key is not None:
if u.identity_map.has_key(key):
return u.identity_map[key]
else:
instance._instance_key = key
u.identity_map[key] = instance
else:
u.register_new(instance)
return instance
class UOWListElement(attributes.ListElement):
def __init__(self, obj, key, data=None, deleteremoved=False, **kwargs):
@@ -94,7 +119,7 @@ class UOWListElement(attributes.ListElement):
self.deleteremoved = deleteremoved
def list_value_changed(self, obj, key, item, listval, isdelete):
uow().modified_lists.append(self)
if isdelete and self.deleteremoved:
if self.deleteremoved and isdelete:
uow().register_deleted(item)
def append(self, item, _mapper_nohistory = False):
if _mapper_nohistory:
@@ -203,6 +228,12 @@ class UnitOfWork(object):
# happen wtihin PropertyLoader.process_dependencies ?
mapper.register_deleted(obj, self)
def unregister_deleted(self, obj):
try:
self.deleted.remove(obj)
except KeyError:
pass
# TODO: tie in register_new/register_dirty with table transaction begins ?
def begin(self):
u = UnitOfWork(self, True)
@@ -297,7 +328,13 @@ class UOWTransaction(object):
refreshed/updated to reflect a recent save/upcoming delete operation, but not a full
save/delete operation on the object itself, unless an additional save/delete
registration is entered for the object."""
#print "RO", str(obj), str(isdelete), str(listonly)
#print "REGISTER", repr(obj), repr(getattr(obj, '_instance_key', None)), str(isdelete), str(listonly)
# things can get really confusing if theres duplicate instances floating around,
# so make sure everything is OK
if hasattr(obj, '_instance_key') and not self.uow.identity_map.has_key(obj._instance_key):
raise "Detected a mapped object not present in the current thread's Identity Map: '%s'. Use objectstore.import_instance() to place deserialized instances or instances from other threads" % repr(obj._instance_key)
mapper = object_mapper(obj)
self.mappers.append(mapper)
task = self.get_task_by_mapper(mapper)