[Sqlalchemy-commits] [1306] sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py: Updates to ActiveMa
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-20 21:04:13
|
<!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>[1306] sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py: Updates to ActiveMapper contributed by Gabriel Jacobo.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1306</dd> <dt>Author</dt> <dd>cleverdevil</dd> <dt>Date</dt> <dd>2006-04-20 16:04:03 -0500 (Thu, 20 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>Updates to ActiveMapper contributed by Gabriel Jacobo. The main purpose of the changes is to ensure that relationships are properly detected and built in the proper order. This should fix some problems that people were having with ActiveMapper requiring classes to be declared in a specific order.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyextactivemapperpy">sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyextactivemapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py (1305 => 1306)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py 2006-04-20 20:38:02 UTC (rev 1305) +++ sqlalchemy/trunk/lib/sqlalchemy/ext/activemapper.py 2006-04-20 21:04:03 UTC (rev 1306) </span><span class="lines">@@ -65,15 +65,44 @@ </span><span class="cx"> # </span><span class="cx"> </span><span class="cx"> __deferred_classes__ = [] </span><del>-def process_relationships(klass, was_deferred=False): </del><ins>+__processed_classes__ = [] + +def check_relationships(klass): + #Check the class for foreign_keys recursively. If some foreign table is not found, the processing of the table + #must be defered. + for keyname in klass.table._foreign_keys: + xtable = keyname._colspec[:keyname._colspec.find('.')] + tablefound = False + for xclass in ActiveMapperMeta.classes: + if ActiveMapperMeta.classes[xclass].table.from_name == xtable: + tablefound = True + break + if tablefound==False: + #The refered table has not yet been created. + return False + + return True + + +def process_relationships(klass): </ins><span class="cx"> defer = False </span><span class="cx"> for propname, reldesc in klass.relations.items(): </span><del>- if not reldesc.classname in ActiveMapperMeta.classes: - if not was_deferred: __deferred_classes__.append(klass) </del><ins>+ #We require that every related table has been processed first + if not reldesc.classname in __processed_classes__: + if not klass._classname in __deferred_classes__: __deferred_classes__.append(klass._classname) </ins><span class="cx"> defer = True </span><del>- </del><ins>+ + + #Check every column item to see if it points to an existing table + #if it does not, defer... </ins><span class="cx"> if not defer: </span><ins>+ if not check_relationships(klass): + if not klass._classname in __deferred_classes__: __deferred_classes__.append(klass._classname) + defer = True + + if not defer: </ins><span class="cx"> relations = {} </span><ins>+ __processed_classes__.append(klass._classname) </ins><span class="cx"> for propname, reldesc in klass.relations.items(): </span><span class="cx"> relclass = ActiveMapperMeta.classes[reldesc.classname] </span><span class="cx"> relations[propname] = relation(relclass.mapper, </span><span class="lines">@@ -82,38 +111,39 @@ </span><span class="cx"> private=reldesc.private, </span><span class="cx"> lazy=reldesc.lazy, </span><span class="cx"> uselist=reldesc.uselist) </span><del>- assign_mapper(klass, klass.table, properties=relations, - inherits=getattr(klass, "_base_mapper", None)) - if was_deferred: __deferred_classes__.remove(klass) - - if not was_deferred: </del><ins>+ if len(relations)>0: + assign_mapper(klass, klass.table, properties=relations) + + if klass._classname in __deferred_classes__: __deferred_classes__.remove(klass._classname) + </ins><span class="cx"> for deferred_class in __deferred_classes__: </span><del>- process_relationships(deferred_class, was_deferred=True) </del><ins>+ process_relationships(ActiveMapperMeta.classes[deferred_class]) </ins><span class="cx"> </span><span class="cx"> </span><span class="cx"> </span><ins>+ </ins><span class="cx"> class ActiveMapperMeta(type): </span><span class="cx"> classes = {} </span><del>- </del><ins>+ </ins><span class="cx"> def __init__(cls, clsname, bases, dict): </span><span class="cx"> table_name = clsname.lower() </span><span class="cx"> columns = [] </span><span class="cx"> relations = {} </span><span class="cx"> _engine = getattr( sys.modules[cls.__module__], "__engine__", engine ) </span><del>- </del><ins>+ </ins><span class="cx"> if 'mapping' in dict: </span><span class="cx"> members = inspect.getmembers(dict.get('mapping')) </span><span class="cx"> for name, value in members: </span><span class="cx"> if name == '__table__': </span><span class="cx"> table_name = value </span><span class="cx"> continue </span><del>- </del><ins>+ </ins><span class="cx"> if '__engine__' == name: </span><span class="cx"> _engine= value </span><span class="cx"> continue </span><del>- </del><ins>+ </ins><span class="cx"> if name.startswith('__'): continue </span><del>- </del><ins>+ </ins><span class="cx"> if isinstance(value, column): </span><span class="cx"> if value.foreign_key: </span><span class="cx"> col = Column(value.colname or name, </span><span class="lines">@@ -128,7 +158,7 @@ </span><span class="cx"> *value.args, **value.kwargs) </span><span class="cx"> columns.append(col) </span><span class="cx"> continue </span><del>- </del><ins>+ </ins><span class="cx"> if isinstance(value, relationship): </span><span class="cx"> relations[name] = value </span><span class="cx"> assert _engine is not None, "No engine specified" </span><span class="lines">@@ -140,16 +170,16 @@ </span><span class="cx"> else: </span><span class="cx"> assign_mapper(cls, cls.table) </span><span class="cx"> cls.relations = relations </span><ins>+ cls._classname = clsname </ins><span class="cx"> ActiveMapperMeta.classes[clsname] = cls </span><del>- </del><span class="cx"> process_relationships(cls) </span><del>- </del><ins>+ </ins><span class="cx"> super(ActiveMapperMeta, cls).__init__(clsname, bases, dict) </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> class ActiveMapper(object): </span><span class="cx"> __metaclass__ = ActiveMapperMeta </span><del>- </del><ins>+ </ins><span class="cx"> def set(self, **kwargs): </span><span class="cx"> for key, value in kwargs.items(): </span><span class="cx"> setattr(self, key, value) </span><span class="lines">@@ -161,5 +191,4 @@ </span><span class="cx"> </span><span class="cx"> def create_tables(): </span><span class="cx"> for klass in ActiveMapperMeta.classes.values(): </span><del>- klass.table.create() - </del><ins>+ klass.table.create() </ins><span class="cx">\ No newline at end of file </span></span></pre> </div> </div> </body> </html> |