[Sqlalchemy-commits] [1297] sqlalchemy/branches/schema/test: merge 1282:1296 from trunk
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-04-19 19:43:45
|
<!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>[1297] sqlalchemy/branches/schema/test: merge 1282:1296 from trunk</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1297</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-04-19 14:43:31 -0500 (Wed, 19 Apr 2006)</dd> </dl> <h3>Log Message</h3> <pre>merge 1282:1296 from trunk</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemybranchesschemalibsqlalchemyattributespy">sqlalchemy/branches/schema/lib/sqlalchemy/attributes.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingobjectstorepy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingpropertiespy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymappingquerypy">sqlalchemy/branches/schema/lib/sqlalchemy/mapping/query.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemymodsselectresultspy">sqlalchemy/branches/schema/lib/sqlalchemy/mods/selectresults.py</a></li> <li><a href="#sqlalchemybranchesschemalibsqlalchemysqlpy">sqlalchemy/branches/schema/lib/sqlalchemy/sql.py</a></li> <li><a href="#sqlalchemybranchesschematestalltestspy">sqlalchemy/branches/schema/test/alltests.py</a></li> <li><a href="#sqlalchemybranchesschematestattributespy">sqlalchemy/branches/schema/test/attributes.py</a></li> <li><a href="#sqlalchemybranchesschematestmanytomanypy">sqlalchemy/branches/schema/test/manytomany.py</a></li> <li><a href="#sqlalchemybranchesschematestmasscreatepy">sqlalchemy/branches/schema/test/masscreate.py</a></li> <li><a href="#sqlalchemybranchesschematestrelationshipspy">sqlalchemy/branches/schema/test/relationships.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemybranchesschematestmassloadpy">sqlalchemy/branches/schema/test/massload.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemybranchesschemalibsqlalchemyattributespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/attributes.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/attributes.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/attributes.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -78,10 +78,10 @@ </span><span class="cx"> which occurs through the SmartProperty property object ultimately calls upon </span><span class="cx"> ManagedAttribute objects associated with the instance via this dictionary.""" </span><span class="cx"> def __init__(self, obj, key): </span><del>- #self.__obj = weakref.ref(obj) - self.obj = obj </del><ins>+ self.__obj = weakref.ref(obj) + #self.obj = obj </ins><span class="cx"> self.key = key </span><del>- #obj = property(lambda s:s.__obj()) </del><ins>+ obj = property(lambda s:s.__obj()) </ins><span class="cx"> def history(self, **kwargs): </span><span class="cx"> return self </span><span class="cx"> def plain_init(self, *args, **kwargs): </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymappingobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/objectstore.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -179,7 +179,7 @@ </span><span class="cx"> </span><span class="cx"> def expunge(self, *obj): </span><span class="cx"> for o in obj: </span><del>- self.uow.expunge(obj) </del><ins>+ self.uow.expunge(o) </ins><span class="cx"> </span><span class="cx"> def register_clean(self, *obj): </span><span class="cx"> for o in obj: </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/properties.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/properties.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/properties.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -232,13 +232,13 @@ </span><span class="cx"> """determines our 'direction', i.e. do we represent one to many, many to many, etc.""" </span><span class="cx"> #print self.key, repr(self.parent.table.name), repr(self.parent.primarytable.name), repr(self.foreignkey.table.name), repr(self.target), repr(self.foreigntable.name) </span><span class="cx"> </span><del>- if self.parent.table is self.target: </del><ins>+ if self.secondaryjoin is not None: + return PropertyLoader.MANYTOMANY + elif self.parent.table is self.target: </ins><span class="cx"> if self.foreignkey.primary_key: </span><span class="cx"> return PropertyLoader.MANYTOONE </span><span class="cx"> else: </span><span class="cx"> return PropertyLoader.ONETOMANY </span><del>- elif self.secondaryjoin is not None: - return PropertyLoader.MANYTOMANY </del><span class="cx"> elif self.foreigntable == self.mapper.noninherited_table: </span><span class="cx"> return PropertyLoader.ONETOMANY </span><span class="cx"> elif self.foreigntable == self.parent.noninherited_table: </span><span class="lines">@@ -666,13 +666,11 @@ </span><span class="cx"> binary.right = binds.setdefault(binary.right, </span><span class="cx"> sql.BindParamClause(binary.left._label, None, shortname = binary.right.name)) </span><span class="cx"> </span><del>- if secondaryjoin is not None: - lazywhere = sql.and_(primaryjoin, secondaryjoin) - else: - lazywhere = primaryjoin - lazywhere = lazywhere.copy_container() </del><ins>+ lazywhere = primaryjoin.copy_container() </ins><span class="cx"> li = BinaryVisitor(visit_binary) </span><span class="cx"> lazywhere.accept_visitor(li) </span><ins>+ if secondaryjoin is not None: + lazywhere = sql.and_(lazywhere, secondaryjoin) </ins><span class="cx"> return (lazywhere, binds) </span><span class="cx"> </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymappingquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mapping/query.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mapping/query.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mapping/query.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -10,6 +10,7 @@ </span><span class="cx"> import sqlalchemy.util as util </span><span class="cx"> from sqlalchemy.exceptions import * </span><span class="cx"> import mapper </span><ins>+from sqlalchemy.exceptions import * </ins><span class="cx"> </span><span class="cx"> class Query(object): </span><span class="cx"> """encapsulates the object-fetching operations provided by Mappers.""" </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemymodsselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/mods/selectresults.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/mods/selectresults.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/mods/selectresults.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -2,7 +2,6 @@ </span><span class="cx"> </span><span class="cx"> import sqlalchemy.mapping as mapping </span><span class="cx"> </span><del>- </del><span class="cx"> class SelectResultsExt(mapping.MapperExtension): </span><span class="cx"> def select_by(self, query, *args, **params): </span><span class="cx"> return SelectResults(query, query._by_clause(*args, **params)) </span></span></pre></div> <a id="sqlalchemybranchesschemalibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/lib/sqlalchemy/sql.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/lib/sqlalchemy/sql.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/lib/sqlalchemy/sql.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -130,7 +130,8 @@ </span><span class="cx"> def between_(ctest, cleft, cright): </span><span class="cx"> """ returns BETWEEN predicate clause (clausetest BETWEEN clauseleft AND clauseright) """ </span><span class="cx"> return BooleanExpression(ctest, and_(cleft, cright), 'BETWEEN') </span><del>- </del><ins>+between = between_ + </ins><span class="cx"> def cast(clause, totype, **kwargs): </span><span class="cx"> """ returns CAST function CAST(clause AS totype) </span><span class="cx"> Use with a sqlalchemy.types.TypeEngine object, i.e </span><span class="lines">@@ -541,6 +542,8 @@ </span><span class="cx"> return Label(name, self, self.type) </span><span class="cx"> def distinct(self): </span><span class="cx"> return CompoundClause(None,"DISTINCT", self) </span><ins>+ def between(self, cleft, cright): + return between_(self, cleft, cright) </ins><span class="cx"> def op(self, operator): </span><span class="cx"> return lambda other: self._compare(operator, other) </span><span class="cx"> # and here come the math operators: </span></span></pre></div> <a id="sqlalchemybranchesschematestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/alltests.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/alltests.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/test/alltests.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -39,6 +39,7 @@ </span><span class="cx"> </span><span class="cx"> # ORM persistence </span><span class="cx"> 'objectstore', </span><ins>+ 'relationships', </ins><span class="cx"> </span><span class="cx"> # cyclical ORM persistence </span><span class="cx"> 'cycles', </span></span></pre></div> <a id="sqlalchemybranchesschematestattributespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/attributes.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/attributes.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/test/attributes.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -43,9 +43,9 @@ </span><span class="cx"> manager.register_attribute(MyTest, 'user_id', uselist = False) </span><span class="cx"> manager.register_attribute(MyTest, 'user_name', uselist = False) </span><span class="cx"> manager.register_attribute(MyTest, 'email_address', uselist = False) </span><del>- x = MyTest() - x.user_id=7 - pickle.dumps(x) </del><ins>+ x = MyTest() + x.user_id=7 + pickle.dumps(x) </ins><span class="cx"> </span><span class="cx"> def testlist(self): </span><span class="cx"> class User(object):pass </span></span></pre></div> <a id="sqlalchemybranchesschematestmanytomanypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/manytomany.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/manytomany.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/test/manytomany.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -7,6 +7,10 @@ </span><span class="cx"> '''represents a place''' </span><span class="cx"> def __init__(self, name=None): </span><span class="cx"> self.name = name </span><ins>+ def __str__(self): + return "(Place '%s')" % self.name + def __repr__(self): + return str(self) </ins><span class="cx"> </span><span class="cx"> class PlaceThingy(object): </span><span class="cx"> '''represents a thingy attached to a Place''' </span><span class="lines">@@ -58,29 +62,87 @@ </span><span class="cx"> Column('transition_id', Integer, ForeignKey('transition.transition_id')), </span><span class="cx"> ) </span><span class="cx"> </span><ins>+ global place_place + place_place = Table('place_place', db, + Column('pl1_id', Integer, ForeignKey('place.place_id')), + Column('pl2_id', Integer, ForeignKey('place.place_id')), + ) + </ins><span class="cx"> place.create() </span><span class="cx"> transition.create() </span><span class="cx"> place_input.create() </span><span class="cx"> place_output.create() </span><span class="cx"> place_thingy.create() </span><ins>+ place_place.create() </ins><span class="cx"> </span><span class="cx"> def tearDownAll(self): </span><ins>+ place_place.drop() </ins><span class="cx"> place_input.drop() </span><span class="cx"> place_output.drop() </span><span class="cx"> place_thingy.drop() </span><span class="cx"> place.drop() </span><span class="cx"> transition.drop() </span><ins>+ #testbase.db.tables.clear() </ins><span class="cx"> </span><span class="cx"> def setUp(self): </span><span class="cx"> objectstore.clear() </span><span class="cx"> clear_mappers() </span><span class="cx"> </span><span class="cx"> def tearDown(self): </span><ins>+ place_place.delete().execute() </ins><span class="cx"> place_input.delete().execute() </span><span class="cx"> place_output.delete().execute() </span><span class="cx"> transition.delete().execute() </span><span class="cx"> place.delete().execute() </span><span class="cx"> </span><ins>+ def testcircular(self): + """tests a many-to-many relationship from a table to itself.""" + + Place.mapper = mapper(Place, place) + + Place.mapper.add_property('places', relation( + Place.mapper, secondary=place_place, primaryjoin=place.c.place_id==place_place.c.pl1_id, + secondaryjoin=place.c.place_id==place_place.c.pl2_id, + order_by=place_place.c.pl2_id, + lazy=True, + )) + + p1 = Place('place1') + p2 = Place('place2') + p3 = Place('place3') + p4 = Place('place4') + p5 = Place('place5') + p6 = Place('place6') + p7 = Place('place7') + + p1.places.append(p2) + p1.places.append(p3) + p5.places.append(p6) + p6.places.append(p1) + p7.places.append(p1) + p1.places.append(p5) + p4.places.append(p3) + p3.places.append(p4) + objectstore.flush() + + objectstore.clear() + l = Place.mapper.select(order_by=place.c.place_id) + (p1, p2, p3, p4, p5, p6, p7) = l + assert p1.places == [p2,p3,p5] + assert p5.places == [p6] + assert p7.places == [p1] + assert p6.places == [p1] + assert p4.places == [p3] + assert p3.places == [p4] + assert p2.places == [] + + for p in l: + pp = p.places + self.echo("Place " + str(p) +" places " + repr(pp)) + + objectstore.delete(p1,p2,p3,p4,p5,p6,p7) + objectstore.flush() + </ins><span class="cx"> def testdouble(self): </span><span class="cx"> """tests that a mapper can have two eager relations to the same table, via </span><span class="cx"> two different association tables. aliases are required.""" </span><span class="lines">@@ -110,17 +172,14 @@ </span><span class="cx"> } </span><span class="cx"> ) </span><span class="cx"> </span><del>- def testcircular(self): - """tests a circular many-to-many relationship. this requires that the mapper - "break off" a new "mapper stub" to indicate a third depedendent processor.""" </del><ins>+ def testbidirectional(self): + """tests a bi-directional many-to-many relationship.""" </ins><span class="cx"> Place.mapper = mapper(Place, place) </span><span class="cx"> Transition.mapper = mapper(Transition, transition, properties = dict( </span><span class="cx"> inputs = relation(Place.mapper, place_output, lazy=True, backref='inputs'), </span><span class="cx"> outputs = relation(Place.mapper, place_input, lazy=True, backref='outputs'), </span><span class="cx"> ) </span><span class="cx"> ) </span><del>- #Place.mapper.add_property('inputs', relation(Transition.mapper, place_output, lazy=True, attributeext=attr.ListBackrefExtension('inputs'))) - #Place.mapper.add_property('outputs', relation(Transition.mapper, place_input, lazy=True, attributeext=attr.ListBackrefExtension('outputs'))) </del><span class="cx"> </span><span class="cx"> Place.eagermapper = Place.mapper.options( </span><span class="cx"> eagerload('inputs', selectalias='ip_alias'), </span><span class="lines">@@ -167,6 +226,7 @@ </span><span class="cx"> enrolTbl.drop() </span><span class="cx"> studentTbl.drop() </span><span class="cx"> courseTbl.drop() </span><ins>+ #testbase.db.tables.clear() </ins><span class="cx"> </span><span class="cx"> def setUp(self): </span><span class="cx"> objectstore.clear() </span><span class="lines">@@ -242,6 +302,7 @@ </span><span class="cx"> c2a1.drop() </span><span class="cx"> a.drop() </span><span class="cx"> c.drop() </span><ins>+ #testbase.db.tables.clear() </ins><span class="cx"> </span><span class="cx"> def testbasic(self): </span><span class="cx"> class C(object):pass </span></span></pre></div> <a id="sqlalchemybranchesschematestmasscreatepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/branches/schema/test/masscreate.py (1296 => 1297)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/branches/schema/test/masscreate.py 2006-04-19 19:33:51 UTC (rev 1296) +++ sqlalchemy/branches/schema/test/masscreate.py 2006-04-19 19:43:31 UTC (rev 1297) </span><span class="lines">@@ -2,6 +2,7 @@ </span><span class="cx"> </span><span class="cx"> from sqlalchemy.attributes import * </span><span class="cx"> import time </span><ins>+import gc </ins><span class="cx"> </span><span class="cx"> manage_attributes = True </span><span class="cx"> init_attributes = manage_attributes and True </span><span class="lines">@@ -32,7 +33,9 @@ </span><span class="cx"> if init_attributes: </span><span class="cx"> attr_manager.init_attr(a) </span><span class="cx"> a.email = 'fo...@ba...' </span><del>- u.addresses.append(u) - </del><ins>+ u.addresses.append(a) +# gc.collect() + print len(managed_attributes) +# managed_attributes.clear() </ins><span class="cx"> total = time.time() - now </span><span class="cx"> print "Total time", total </span></span></pre></div> <a id="sqlalchemybranchesschematestmassloadpyfromrev1296sqlalchemytrunktestmassloadpy"></a> <div class="copfile"><h4>Copied: sqlalchemy/branches/schema/test/massload.py (from rev 1296, sqlalchemy/trunk/test/massload.py) ( => )</h4> <pre class="diff"><span> <span class="info">Modified: sqlalchemy/branches/schema/test/relationships.py =================================================================== </span><del>--- sqlalchemy/branches/schema/test/relationships.py 2006-04-19 19:33:51 UTC (rev 1296) </del><ins>+++ sqlalchemy/branches/schema/test/relationships.py 2006-04-19 19:43:31 UTC (rev 1297) </ins><span class="lines">@@ -10,9 +10,13 @@ </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> class RelationTest(testbase.PersistTest): </span><del>- """this is essentially an extension of the "dependency.py" topological sort test. this exposes - a particular issue that doesnt always occur with the straight dependency tests, due to the nature - of the sort being different based on random conditions""" </del><ins>+ """this is essentially an extension of the "dependency.py" topological sort test. + in this test, a table is dependent on two other tables that are otherwise unrelated to each other. + the dependency sort must insure that this childmost table is below both parent tables in the outcome + (a bug existed where this was not always the case). + while the straight topological sort tests should expose this, since the sorting can be different due + to subtle differences in program execution, this test case was exposing the bug whereas the simpler tests + were not.""" </ins><span class="cx"> def setUpAll(self): </span><span class="cx"> global tbl_a </span><span class="cx"> global tbl_b </span><span class="lines">@@ -83,6 +87,9 @@ </span><span class="cx"> conn.drop(tbl_c) </span><span class="cx"> conn.drop(tbl_b) </span><span class="cx"> conn.drop(tbl_a) </span><ins>+ + def tearDownAll(self): + testbase.metadata.tables.clear() </ins><span class="cx"> </span><span class="cx"> def testDeleteRootTable(self): </span><span class="cx"> session.flush() </span></span></pre> </div> </div> </body> </html> |