this method returns or creates the single per-transaction instance of
UOWTask that exists for that mapper."""
+ if isinstance(mapper, UOWTask):
def execute(self, echo=False):
+ #print "\n------------------\nEXECUTE"
+ #for task in self.tasks.values():
+ # print "\nTASK:", task
+ # for obj in task.objects:
+ # print "TASK OBJ:", obj
+ # for elem in task.get_elements(polymorphic=True):
+ # print "POLYMORPHIC TASK OBJ:", elem.obj
+ #print "-----------------------------"
# pre-execute dependency processors. this process may
# result in new tasks, objects and/or dependency processors being added,
# particularly with 'delete-orphan' cascade rules.
- for task in self.tasks.values():
- def inheriting_tasks(task):
- if task.mapper not in mappers:
- for mapper in task.mapper._inheriting_mappers:
- inherit_task = self.tasks.get(mapper, None)
- if inherit_task is None:
- for task in self.tasks.values():
+ mappers = self._get_noninheriting_mappers()
head = DependencySorter(self.dependencies, list(mappers)).sort(allow_all_cycles=True)
+ #print "-------------------------"
+ #print "---------------------------"
+ def _get_noninheriting_mappers(self):
+ """returns a list of UOWTasks whose mappers are not inheriting from the mapper of another UOWTask.
+ i.e., this returns the root UOWTasks for all the inheritance hierarchies represented in this UOWTransaction."""
+ for task in self.tasks.values():
+ base = task.mapper.base_mapper()
"""an element within a UOWTask. corresponds to a single object instance
to be saved, deleted, or just part of the transaction as a placeholder for
def __init__(self, processor, targettask):
self.processor = processor
self.targettask = targettask
return other.processor is self.processor and other.targettask is self.targettask
elements = [getobj(elem) for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)]
"""represents the full list of objects that are to be saved/deleted by a specific Mapper."""
- def __init__(self, uowtransaction, mapper):
- if uowtransaction is not None:
+ def __init__(self, uowtransaction, mapper, circular_parent=None):
+ if not circular_parent:
uowtransaction.tasks[mapper] = self
# the transaction owning this UOWTask
self.uowtransaction = uowtransaction
# a list of UOWTasks that correspond to Mappers which are inheriting
# mappers of this UOWTask's Mapper
- self.inheriting_tasks =
+ self.inheriting_tasks =
# whether this UOWTask is circular, meaning it holds a second
- # UOWTask that contains a special row-based dependency structure
+ # UOWTask that contains a special row-based dependency structure
+ # for a task thats part of that row-based dependency structure, points
+ # back to the "public facing" task.
+ self.circular_parent = circular_parent
# a list of UOWDependencyProcessors are derived from the main
# set of dependencies, referencing sub-UOWTasks attached to this
# one which represent portions of the total list of objects.
+ def _inheriting_tasks(self):
+ """returns an iterator of UOWTasks whos mappers inherit from this UOWTask's mapper. Only
+ goes one level deep; i.e. for each UOWTask returned, you would call _inheriting_tasks on those
+ to get their inheriting tasks. For a multilevel-inheritance chain, i.e. A->B->C, and there are
+ UOWTasks for A and C but not B, C will be returned when this method is called on A, otherwise B."""
+ if self.circular_parent is not None:
+ def _tasks_by_mapper(mapper):
+ for m in mapper._inheriting_mappers:
+ inherit_task = self.uowtransaction.tasks.get(m, None)
+ if inherit_task is not None:
+ #for t in inherit_task._inheriting_tasks():
+ for t in _tasks_by_mapper(m):
+ for t in _tasks_by_mapper(self.mapper):
+ inheriting_tasks = property(_inheriting_tasks)
for task in self.inheriting_tasks:
def get_elements(self, polymorphic=False):
for rec in self.objects.values():
- for task in self.inheriting_tasks:
- for rec in task.get_elements(polymorphic=True):
+ for task in self.inheriting_tasks:
+ for rec in task.get_elements(polymorphic=True):
polymorphic_tosave_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if not rec.isdelete])
polymorphic_todelete_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if rec.isdelete])
- l = UOWTask(
+ l = UOWTask(, depprocessor.targettask.mapper)
- proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper(), True)
- return dep.targettask in cycles and (proctask is not None and proctask in cycles)
+ proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper().base_mapper(), True)
+ targettask = trans.get_task_by_mapper(dep.targettask.mapper.base_mapper(), True)
+ return targettask in cycles and (proctask is not None and proctask in cycles)
# organize all original UOWDependencyProcessors by their target task
for dep in deps_by_targettask.get(task, ):
# is this dependency involved in one of the cycles ?
- #print "DEP iterate", dep.processor.key
+ #print "DEP iterate", dep.processor.key
if not dependency_in_cycles(dep):
#print "DEP", dep.processor.key
(processor, targettask) = (dep.processor, dep.targettask)
originating_task = object_to_original_task[obj]
- return hierarchical_tasks.setdefault(obj, UOWTask(
Non e, originating_task.mapper))
+ return hierarchical_tasks.setdefault(obj, UOWTask(on, originating_task.mapper))
def make_task_tree(node, parenttask):
"""takes a dependency-sorted tree of objects and creates a tree of UOWTasks"""
# this is the new "circular" UOWTask which will execute in place of "self"
- t = UOWTask(
+ t = UOWTask()
# stick the non-circular dependencies and child tasks onto the new