[Sqlalchemy-commits] [1510] sqlalchemy/trunk/lib/sqlalchemy/orm: pretty major change to inheritance
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-05-25 17:53:18
|
<!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>[1510] sqlalchemy/trunk/lib/sqlalchemy/orm: pretty major change to inheritance topological sorting - mapper dependencies are calculated</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1510</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-25 12:53:06 -0500 (Thu, 25 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>pretty major change to inheritance topological sorting - mapper dependencies are calculated based on their ultimate "base inherited" mapper, UOWTasks organized into recursive inheritance structures based on the inheritance of the mappers. this allows tasks across a class/mapper inheritance hierarchy to properly interact with other dependency processors and sub-tasks.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormdependencypy">sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormmapperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyormdependencypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py (1509 => 1510)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-25 16:23:39 UTC (rev 1509) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-25 17:53:06 UTC (rev 1510) </span><span class="lines">@@ -203,7 +203,7 @@ </span><span class="cx"> uowcommit.register_object(obj, postupdate=True) </span><span class="cx"> </span><span class="cx"> def preprocess_dependencies(self, task, deplist, uowcommit, delete = False): </span><del>- #print self.mapper.table.name + " " + self.key + " " + repr(len(deplist)) + " process_dep isdelete " + repr(delete) + " direction " + repr(self.direction) </del><ins>+ #print self.mapper.mapped_table.name + " " + self.key + " " + repr(len(deplist)) + " PRE process_dep isdelete " + repr(delete) + " direction " + repr(self.direction) </ins><span class="cx"> # TODO: post_update instructions should be established in this step as well </span><span class="cx"> # (and executed in the regular traversal) </span><span class="cx"> if self.post_update: </span><span class="lines">@@ -359,6 +359,7 @@ </span><span class="cx"> for the many-to-many update task.""" </span><span class="cx"> def __init__(self, mapper): </span><span class="cx"> self.mapper = mapper </span><ins>+ self._inheriting_mappers = [] </ins><span class="cx"> def register_dependencies(self, uowcommit): </span><span class="cx"> pass </span><span class="cx"> def save_obj(self, *args, **kwargs): </span><span class="lines">@@ -367,3 +368,5 @@ </span><span class="cx"> pass </span><span class="cx"> def _primary_mapper(self): </span><span class="cx"> return self </span><ins>+ def base_mapper(self): + return self </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1509 => 1510)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-25 16:23:39 UTC (rev 1509) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-25 17:53:06 UTC (rev 1510) </span><span class="lines">@@ -282,6 +282,13 @@ </span><span class="cx"> elif (isinstance(column, list) and sql.is_column(column[0])): </span><span class="cx"> props[key] = [self.select_table.corresponding_column(c) for c in prop] </span><span class="cx"> self.__surrogate_mapper = Mapper(self.class_, self.select_table, non_primary=True, properties=props, polymorphic_map=self.polymorphic_map, polymorphic_on=self.polymorphic_on) </span><ins>+ + def base_mapper(self): + """returns the ultimate base mapper in an inheritance chain""" + if self.inherits is not None: + return self.inherits.base_mapper() + else: + return self </ins><span class="cx"> </span><span class="cx"> def add_polymorphic_mapping(self, key, class_or_mapper, entity_name=None): </span><span class="cx"> if isinstance(class_or_mapper, type): </span><span class="lines">@@ -640,7 +647,6 @@ </span><span class="cx"> if primary_key is not None: </span><span class="cx"> i = 0 </span><span class="cx"> for col in self.pks_by_table[table]: </span><del>- #print "col: " + table.name + "." + col.key + " val: " + repr(self._getattrbycolumn(obj, col)) </del><span class="cx"> if self._getattrbycolumn(obj, col) is None: </span><span class="cx"> self._setattrbycolumn(obj, col, primary_key[i]) </span><span class="cx"> i+=1 </span><span class="lines">@@ -722,8 +728,6 @@ </span><span class="cx"> objects which will process lists of objects in between saves and deletes.""" </span><span class="cx"> for prop in self.props.values(): </span><span class="cx"> prop.register_dependencies(uowcommit, *args, **kwargs) </span><del>- if self.inherits is not None: - uowcommit.register_dependency(self.inherits, self) </del><span class="cx"> </span><span class="cx"> def cascade_iterator(self, type, object, recursive=None): </span><span class="cx"> if recursive is None: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1509 => 1510)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-25 16:23:39 UTC (rev 1509) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-25 17:53:06 UTC (rev 1510) </span><span class="lines">@@ -333,7 +333,10 @@ </span><span class="cx"> """called by mapper.PropertyLoader to register the objects handled by </span><span class="cx"> one mapper being dependent on the objects handled by another.""" </span><span class="cx"> # correct for primary mapper (the mapper offcially associated with the class) </span><del>- self.dependencies[(mapper._primary_mapper(), dependency._primary_mapper())] = True </del><ins>+ mapper = mapper._primary_mapper().base_mapper() + dependency = dependency._primary_mapper().base_mapper() + + self.dependencies[(mapper, dependency)] = True </ins><span class="cx"> self._mark_modified() </span><span class="cx"> </span><span class="cx"> def register_processor(self, mapper, processor, mapperfrom): </span><span class="lines">@@ -349,6 +352,7 @@ </span><span class="cx"> # correct for primary mapper (the mapper offcially associated with the class) </span><span class="cx"> mapper = mapper._primary_mapper() </span><span class="cx"> mapperfrom = mapperfrom._primary_mapper() </span><ins>+ </ins><span class="cx"> task = self.get_task_by_mapper(mapper) </span><span class="cx"> targettask = self.get_task_by_mapper(mapperfrom) </span><span class="cx"> up = UOWDependencyProcessor(processor, targettask) </span><span class="lines">@@ -422,7 +426,21 @@ </span><span class="cx"> mappers = util.HashSet() </span><span class="cx"> for task in self.tasks.values(): </span><span class="cx"> mappers.append(task.mapper) </span><del>- </del><ins>+ + def inheriting_tasks(task): + if task.mapper not in mappers: + return + for mapper in task.mapper._inheriting_mappers: + inherit_task = self.tasks.get(mapper, None) + if inherit_task is None: + continue + inheriting_tasks(inherit_task) + task.inheriting_tasks.append(inherit_task) + del mappers[mapper] + + for task in self.tasks.values(): + inheriting_tasks(task) + </ins><span class="cx"> head = DependencySorter(self.dependencies, mappers).sort(allow_all_cycles=True) </span><span class="cx"> #print str(head) </span><span class="cx"> task = sort_hier(head) </span><span class="lines">@@ -525,6 +543,7 @@ </span><span class="cx"> self.cyclical_dependencies = [] </span><span class="cx"> self.circular = None </span><span class="cx"> self.childtasks = [] </span><ins>+ self.inheriting_tasks = [] </ins><span class="cx"> </span><span class="cx"> def is_empty(self): </span><span class="cx"> return len(self.objects) == 0 and len(self.dependencies) == 0 and len(self.childtasks) == 0 </span><span class="lines">@@ -563,7 +582,28 @@ </span><span class="cx"> del self.objects[obj] </span><span class="cx"> except KeyError: </span><span class="cx"> pass </span><del>- </del><ins>+ + def _save_objects(self, trans): + self.mapper.save_obj(self.tosave_objects, trans) + for task in self.inheriting_tasks: + task._save_objects(trans) + def _delete_objects(self, trans): + self.mapper.delete_obj(self.todelete_objects, trans) + for task in self.inheriting_tasks: + task._delete_objects(trans) + def _execute_dependencies(self, trans): + for dep in self.dependencies: + dep.execute(trans, False) + for task in self.inheriting_tasks: + task._execute_dependencies(trans) + for dep in self.dependencies: + dep.execute(trans, True) + def _execute_childtasks(self, trans): + for child in self.childtasks: + child.execute(trans) + for task in self.inheriting_tasks: + task._execute_childtasks(trans) + </ins><span class="cx"> def execute(self, trans): </span><span class="cx"> """executes this UOWTask. saves objects to be saved, processes all dependencies </span><span class="cx"> that have been registered, and deletes objects to be deleted. """ </span><span class="lines">@@ -571,24 +611,20 @@ </span><span class="cx"> self.circular.execute(trans) </span><span class="cx"> return </span><span class="cx"> </span><del>- self.mapper.save_obj(self.tosave_objects, trans) </del><ins>+ self._save_objects(trans) </ins><span class="cx"> for dep in self.cyclical_dependencies: </span><span class="cx"> dep.execute(trans, False) </span><span class="cx"> for element in self.tosave_elements: </span><span class="cx"> for task in element.childtasks: </span><span class="cx"> task.execute(trans) </span><del>- for dep in self.dependencies: - dep.execute(trans, False) - for dep in self.dependencies: - dep.execute(trans, True) </del><ins>+ self._execute_dependencies(trans) </ins><span class="cx"> for dep in self.cyclical_dependencies: </span><span class="cx"> dep.execute(trans, True) </span><del>- for child in self.childtasks: - child.execute(trans) </del><ins>+ self._execute_childtasks(trans) </ins><span class="cx"> for element in self.todelete_elements: </span><span class="cx"> for task in element.childtasks: </span><span class="cx"> task.execute(trans) </span><del>- self.mapper.delete_obj(self.todelete_objects, trans) </del><ins>+ self._delete_objects(trans) </ins><span class="cx"> </span><span class="cx"> tosave_elements = property(lambda self: [rec for rec in self.objects.values() if not rec.isdelete]) </span><span class="cx"> todelete_elements = property(lambda self:[rec for rec in self.objects.values() if rec.isdelete]) </span><span class="lines">@@ -808,6 +844,47 @@ </span><span class="cx"> def _repr(obj): </span><span class="cx"> return "%s(%d)" % (obj.__class__.__name__, id(obj)) </span><span class="cx"> </span><ins>+ def _inheritance_tag(task): + if task is not self: + return (" (inheriting task %s)" % _repr_task(task)) + else: + return "" + + def _dump_saveelements(task): + for rec in task.tosave_elements: + if rec.listonly: + continue + header(buf, _indent() + " |- Save elements"+ _inheritance_tag(task) + "\n") + buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") + for t in task.inheriting_tasks: + _dump_saveelements(t) + + def _dump_deleteelements(task): + for rec in task.todelete_elements: + if rec.listonly: + continue + header(buf, _indent() + " |- Delete elements"+ _inheritance_tag(task) + "\n") + buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") + for t in task.inheriting_tasks: + _dump_deleteelements(t) + + def _dump_dependencies(task): + for dep in task.dependencies: + header(buf, _indent() + " |- Save dependencies" + _inheritance_tag(task) + "\n") + _dump_processor(dep, False) + for t in task.inheriting_tasks: + _dump_dependencies(t) + for dep in task.dependencies: + header(buf, _indent() + " |- Delete dependencies" + _inheritance_tag(task) + "\n") + _dump_processor(dep, True) + + def _dump_childtasks(task): + for child in task.childtasks: + header(buf, _indent() + " |- Child tasks" + _inheritance_tag(task) + "\n") + child._dump(buf, indent + 1) + for t in task.inheriting_tasks: + _dump_childtasks(t) + </ins><span class="cx"> if self.circular is not None: </span><span class="cx"> self.circular._dump(buf, indent, self) </span><span class="cx"> return </span><span class="lines">@@ -822,11 +899,7 @@ </span><span class="cx"> buf.write(i + " " + _repr_task(self)) </span><span class="cx"> </span><span class="cx"> buf.write("\n") </span><del>- for rec in self.tosave_elements: - if rec.listonly: - continue - header(buf, _indent() + " |- Save elements\n") - buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") </del><ins>+ _dump_saveelements(self) </ins><span class="cx"> for dep in self.cyclical_dependencies: </span><span class="cx"> header(buf, _indent() + " |- Cyclical Save dependencies\n") </span><span class="cx"> _dump_processor(dep, False) </span><span class="lines">@@ -834,32 +907,17 @@ </span><span class="cx"> for task in element.childtasks: </span><span class="cx"> header(buf, _indent() + " |- Save subelements of UOWTaskElement(%s)\n" % id(element)) </span><span class="cx"> task._dump(buf, indent + 1) </span><del>- for dep in self.dependencies: - header(buf, _indent() + " |- Save dependencies\n") - _dump_processor(dep, False) - for dep in self.dependencies: - header(buf, _indent() + " |- Delete dependencies\n") - _dump_processor(dep, True) </del><ins>+ _dump_dependencies(self) </ins><span class="cx"> for dep in self.cyclical_dependencies: </span><span class="cx"> header(buf, _indent() + " |- Cyclical Delete dependencies\n") </span><span class="cx"> _dump_processor(dep, True) </span><del>- for child in self.childtasks: - header(buf, _indent() + " |- Child tasks\n") - child._dump(buf, indent + 1) -# for obj in self.postupdate: -# header(buf, _indent() + " |- Post Update objects\n") -# buf.write(_repr(obj) + "\n") </del><ins>+ _dump_childtasks(self) </ins><span class="cx"> for element in self.todelete_elements: </span><span class="cx"> for task in element.childtasks: </span><span class="cx"> header(buf, _indent() + " |- Delete subelements of UOWTaskElement(%s)\n" % id(element)) </span><span class="cx"> task._dump(buf, indent + 1) </span><ins>+ _dump_deleteelements(self) </ins><span class="cx"> </span><del>- for rec in self.todelete_elements: - if rec.listonly: - continue - header(buf, _indent() + " |- Delete elements\n") - buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") - </del><span class="cx"> if self.is_empty(): </span><span class="cx"> buf.write(_indent() + " |- (empty task)\n") </span><span class="cx"> else: </span></span></pre> </div> </div> </body> </html> |