[Sqlalchemy-commits] [1519] sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py: circular dependency s
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-05-27 16:39:16
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1519] sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py: circular dependency sort will not create new UOWTasks/UOWDependencyProcessors mid-stream</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1519</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 11:39:05 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>circular dependency sort will not create new UOWTasks/UOWDependencyProcessors mid-stream further construction on migrating UOWTask to be fully polymorphic</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1518 => 1519)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 05:45:21 UTC (rev 1518) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 16:39:05 UTC (rev 1519) </span><span class="lines">@@ -316,7 +316,7 @@ </span><span class="cx"> # raise "test assertion failed" </span><span class="cx"> self.__modified = True </span><span class="cx"> </span><del>- def get_task_by_mapper(self, mapper): </del><ins>+ def get_task_by_mapper(self, mapper, dontcreate=False): </ins><span class="cx"> """every individual mapper involved in the transaction has a single </span><span class="cx"> corresponding UOWTask object, which stores all the operations involved </span><span class="cx"> with that mapper as well as operations dependent on those operations. </span><span class="lines">@@ -325,6 +325,8 @@ </span><span class="cx"> try: </span><span class="cx"> return self.tasks[mapper] </span><span class="cx"> except KeyError: </span><ins>+ if dontcreate: + return None </ins><span class="cx"> task = UOWTask(self, mapper) </span><span class="cx"> task.mapper.register_dependencies(self) </span><span class="cx"> return task </span><span class="lines">@@ -675,20 +677,29 @@ </span><span class="cx"> self._execute_per_element_childtasks(trans, True) </span><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><del>- def _polymorphic_elements(self): </del><ins>+ def contains_object(self, obj, polymorphic=False): + if obj in self.objects: + return True + if polymorphic: + for task in self.inheriting_tasks: + if task.contains_object(obj, True): + return True + return False + + def get_elements(self, polymorphic=False): </ins><span class="cx"> for rec in self.objects.values(): </span><span class="cx"> yield rec </span><del>- for task in self.inheriting_tasks: - for rec in task._polymorphic_elements(): - yield rec </del><ins>+ if polymorphic: + for task in self.inheriting_tasks: + for rec in task.get_elements(polymorphic=True): + yield rec </ins><span class="cx"> </span><del>- polymorphic_tosave_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if not rec.isdelete]) - polymorphic_todelete_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if rec.isdelete]) - - tosave_elements = property(lambda self: [rec for rec in self.objects.values() if not rec.isdelete]) - todelete_elements = property(lambda self:[rec for rec in self.objects.values() if rec.isdelete]) - tosave_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is False]) - todelete_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is True]) </del><ins>+ 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]) + tosave_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=False) if not rec.isdelete]) + todelete_elements = property(lambda self:[rec for rec in self.get_elements(polymorphic=False) if rec.isdelete]) + tosave_objects = property(lambda self:[rec.obj for rec in self.get_elements(polymorphic=False) if rec.obj is not None and not rec.listonly and rec.isdelete is False]) + todelete_objects = property(lambda self:[rec.obj for rec in self.get_elements(polymorphic=False) if rec.obj is not None and not rec.listonly and rec.isdelete is True]) </ins><span class="cx"> </span><span class="cx"> def _sort_circular_dependencies(self, trans, cycles): </span><span class="cx"> """for a single task, creates a hierarchical tree of "subtasks" which associate </span><span class="lines">@@ -700,7 +711,7 @@ </span><span class="cx"> a hierarchical tree is being represented.""" </span><span class="cx"> allobjects = [] </span><span class="cx"> for task in cycles: </span><del>- allobjects += task.objects.keys() </del><ins>+ allobjects += [e.obj for e in task.get_elements(polymorphic=True)] </ins><span class="cx"> tuples = [] </span><span class="cx"> </span><span class="cx"> cycles = sets.Set(cycles) </span><span class="lines">@@ -732,25 +743,28 @@ </span><span class="cx"> dp[depprocessor] = l </span><span class="cx"> return l </span><span class="cx"> </span><ins>+ def dependency_in_cycles(dep): + proctask = trans.get_task_by_mapper(dep.processor.mapper, True) + return dep.targettask in cycles and (proctask is not None and proctask in cycles) + </ins><span class="cx"> # organize all original UOWDependencyProcessors by their target task </span><span class="cx"> deps_by_targettask = {} </span><span class="cx"> for task in cycles: </span><span class="cx"> for dep in task.dependencies: </span><del>- if dep.targettask not in cycles or trans.get_task_by_mapper(dep.processor.mapper) not in cycles: </del><ins>+ if not dependency_in_cycles(dep): </ins><span class="cx"> extradeplist.append(dep) </span><span class="cx"> l = deps_by_targettask.setdefault(dep.targettask, []) </span><span class="cx"> l.append(dep) </span><span class="cx"> </span><span class="cx"> for task in cycles: </span><del>- for taskelement in task.objects.values(): </del><ins>+ for taskelement in task.get_elements(polymorphic=True): </ins><span class="cx"> obj = taskelement.obj </span><span class="cx"> object_to_original_task[obj] = task </span><span class="cx"> #print "OBJ", repr(obj), "TASK", repr(task) </span><span class="cx"> </span><span class="cx"> for dep in deps_by_targettask.get(task, []): </span><span class="cx"> # is this dependency involved in one of the cycles ? </span><del>- cyclicaldep = dep.targettask in cycles and trans.get_task_by_mapper(dep.processor.mapper) in cycles - if not cyclicaldep: </del><ins>+ if not dependency_in_cycles(dep): </ins><span class="cx"> continue </span><span class="cx"> </span><span class="cx"> (processor, targettask) = (dep.processor, dep.targettask) </span><span class="lines">@@ -758,13 +772,14 @@ </span><span class="cx"> </span><span class="cx"> # list of dependent objects from this object </span><span class="cx"> childlist = dep.get_object_dependencies(obj, trans, passive = True) </span><del>- # the task corresponding to the processor's objects </del><ins>+ + # the task corresponding to saving/deleting of those dependent objects </ins><span class="cx"> childtask = trans.get_task_by_mapper(processor.mapper) </span><span class="cx"> </span><span class="cx"> childlist = childlist.added_items() + childlist.unchanged_items() + childlist.deleted_items() </span><span class="cx"> </span><span class="cx"> for o in childlist: </span><del>- if o is None or o not in childtask.objects: </del><ins>+ if o is None or not childtask.contains_object(o, polymorphic=True): </ins><span class="cx"> continue </span><span class="cx"> whosdep = dep.whose_dependent_on_who(obj, o) </span><span class="cx"> if whosdep is not None: </span><span class="lines">@@ -802,7 +817,7 @@ </span><span class="cx"> </span><span class="cx"> can_add_to_parent = t.mapper is parenttask.mapper </span><span class="cx"> original_task = object_to_original_task[node.item] </span><del>- if original_task.objects.has_key(node.item): </del><ins>+ if original_task.contains_object(node.item, polymorphic=False): </ins><span class="cx"> if can_add_to_parent: </span><span class="cx"> parenttask.append(node.item, original_task.objects[node.item].listonly, isdelete=original_task.objects[node.item].isdelete, childtask=t) </span><span class="cx"> else: </span></span></pre> </div> </div> </body> </html> |