[Sqlalchemy-commits] [6168] sqlalchemy/trunk: - relations() now have greater ability to be " overri
Brought to you by:
zzzeek
From: <co...@sq...> - 2009-07-21 21:47:09
|
<!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><meta http-equiv="content-type" content="text/html; charset=utf-8" /><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, #header, #footer { 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; } #header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; } #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>[6168] sqlalchemy/trunk: - relations() now have greater ability to be " overridden",</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>6168</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2009-07-21 17:47:03 -0400 (Tue, 21 Jul 2009)</dd> </dl> <h3>Log Message</h3> <pre>- relations() now have greater ability to be "overridden", meaning a subclass that explicitly specifies a relation() overriding that of the parent class will be honored during a flush. This is currently to support many-to-many relations from concrete inheritance setups. Outside of that use case, YMMV. [ticket:1477]</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> <li><a href="#sqlalchemytrunktestorminheritancetest_concretepy">sqlalchemy/trunk/test/orm/inheritance/test_concrete.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (6167 => 6168)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2009-07-21 21:07:04 UTC (rev 6167) +++ sqlalchemy/trunk/CHANGES 2009-07-21 21:47:03 UTC (rev 6168) </span><span class="lines">@@ -9,6 +9,13 @@ </span><span class="cx"> - Fixed bug whereby inheritance discriminator part of a </span><span class="cx"> composite primary key would fail on updates. </span><span class="cx"> Continuation of [ticket:1300]. </span><ins>+ + - relations() now have greater ability to be "overridden", + meaning a subclass that explicitly specifies a relation() + overriding that of the parent class will be honored + during a flush. This is currently to support + many-to-many relations from concrete inheritance setups. + Outside of that use case, YMMV. [ticket:1477] </ins><span class="cx"> </span><span class="cx"> - sql </span><span class="cx"> - Fixed a bug in extract() introduced in 0.5.4 whereby </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (6167 => 6168)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2009-07-21 21:07:04 UTC (rev 6167) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2009-07-21 21:47:03 UTC (rev 6168) </span><span class="lines">@@ -430,6 +430,15 @@ </span><span class="cx"> yield rec </span><span class="cx"> return collection </span><span class="cx"> </span><ins>+ def _polymorphic_collection_filtered(fn): + + def collection(self, mappers): + for task in self.polymorphic_tasks: + if task.mapper in mappers: + for rec in fn(task): + yield rec + return collection + </ins><span class="cx"> @property </span><span class="cx"> def elements(self): </span><span class="cx"> return self._objects.values() </span><span class="lines">@@ -438,6 +447,10 @@ </span><span class="cx"> def polymorphic_elements(self): </span><span class="cx"> return self.elements </span><span class="cx"> </span><ins>+ @_polymorphic_collection_filtered + def filter_polymorphic_elements(self): + return self.elements + </ins><span class="cx"> @property </span><span class="cx"> def polymorphic_tosave_elements(self): </span><span class="cx"> return [rec for rec in self.polymorphic_elements if not rec.isdelete] </span><span class="lines">@@ -642,7 +655,19 @@ </span><span class="cx"> def __init__(self, processor, targettask): </span><span class="cx"> self.processor = processor </span><span class="cx"> self.targettask = targettask </span><del>- </del><ins>+ prop = processor.prop + + # define a set of mappers which + # will filter the lists of entities + # this UOWDP processes. this allows + # MapperProperties to be overridden + # at least for concrete mappers. + self._mappers = set([ + m + for m in self.processor.parent.polymorphic_iterator() + if m._props[prop.key] is prop + ]).union(self.processor.mapper.polymorphic_iterator()) + </ins><span class="cx"> def __repr__(self): </span><span class="cx"> return "UOWDependencyProcessor(%s, %s)" % (str(self.processor), str(self.targettask)) </span><span class="cx"> </span><span class="lines">@@ -673,12 +698,16 @@ </span><span class="cx"> return elem.state </span><span class="cx"> </span><span class="cx"> ret = False </span><del>- elements = [getobj(elem) for elem in self.targettask.polymorphic_tosave_elements if self not in elem.preprocessed] </del><ins>+ elements = [getobj(elem) for elem in + self.targettask.filter_polymorphic_elements(self._mappers) + if self not in elem.preprocessed and not elem.isdelete] </ins><span class="cx"> if elements: </span><span class="cx"> ret = True </span><span class="cx"> self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=False) </span><span class="cx"> </span><del>- elements = [getobj(elem) for elem in self.targettask.polymorphic_todelete_elements if self not in elem.preprocessed] </del><ins>+ elements = [getobj(elem) for elem in + self.targettask.filter_polymorphic_elements(self._mappers) + if self not in elem.preprocessed and elem.isdelete] </ins><span class="cx"> if elements: </span><span class="cx"> ret = True </span><span class="cx"> self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=True) </span><span class="lines">@@ -687,11 +716,11 @@ </span><span class="cx"> def execute(self, trans, delete): </span><span class="cx"> """process all objects contained within this ``UOWDependencyProcessor``s target task.""" </span><span class="cx"> </span><del>- if delete: - elements = self.targettask.polymorphic_todelete_elements - else: - elements = self.targettask.polymorphic_tosave_elements </del><span class="cx"> </span><ins>+ elements = [e for e in + self.targettask.filter_polymorphic_elements(self._mappers) + if e.isdelete==delete] + </ins><span class="cx"> self.processor.process_dependencies( </span><span class="cx"> self.targettask, </span><span class="cx"> [elem.state for elem in elements], </span></span></pre></div> <a id="sqlalchemytrunktestorminheritancetest_concretepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/orm/inheritance/test_concrete.py (6167 => 6168)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/orm/inheritance/test_concrete.py 2009-07-21 21:07:04 UTC (rev 6167) +++ sqlalchemy/trunk/test/orm/inheritance/test_concrete.py 2009-07-21 21:47:03 UTC (rev 6168) </span><span class="lines">@@ -464,7 +464,61 @@ </span><span class="cx"> sess.query(C).options(eagerload(C.many_a)).order_by(C.id).all(), </span><span class="cx"> ) </span><span class="cx"> self.assert_sql_count(testing.db, go, 1) </span><ins>+ +class ManyToManyTest(_base.MappedTest): + @classmethod + def define_tables(cls, metadata): + Table("base", metadata, + Column('id', Integer, primary_key=True, test_needs_autoincrement=True) + ) + Table("sub", metadata, + Column('id', Integer, primary_key=True, test_needs_autoincrement=True) + ) + Table("base_mtom", metadata, + Column('base_id', Integer, ForeignKey('base.id'), primary_key=True), + Column('related_id', Integer, ForeignKey('related.id'), primary_key=True) + ) + Table("sub_mtom", metadata, + Column('base_id', Integer, ForeignKey('sub.id'), primary_key=True), + Column('related_id', Integer, ForeignKey('related.id'), primary_key=True) + ) + Table("related", metadata, + Column('id', Integer, primary_key=True, test_needs_autoincrement=True) + ) </ins><span class="cx"> </span><ins>+ @classmethod + @testing.resolve_artifact_names + def setup_classes(cls): + class Base(_base.ComparableEntity): + pass + class Sub(Base): + pass + class Related(_base.ComparableEntity): + pass + + @testing.resolve_artifact_names + def test_selective_relations(self): + mapper(Base, base, properties={ + 'related':relation(Related, secondary=base_mtom, backref='bases', order_by=related.c.id) + }) + mapper(Sub, sub, inherits=Base, concrete=True, properties={ + 'related':relation(Related, secondary=sub_mtom, backref='subs', order_by=related.c.id) + }) + mapper(Related, related) + + sess = sessionmaker()() + + b1, s1, r1, r2, r3 = Base(), Sub(), Related(), Related(), Related() + + b1.related.append(r1) + b1.related.append(r2) + s1.related.append(r2) + s1.related.append(r3) + sess.add_all([b1, s1]) + sess.commit() + + eq_(s1.related, [r2, r3]) + eq_(b1.related, [r1, r2]) </ins><span class="cx"> </span><span class="cx"> class ColKeysTest(_base.MappedTest): </span><span class="cx"> @classmethod </span></span></pre> </div> </div> </body> </html> |