sqlalchemy-commits Mailing List for SQLAlchemy (Page 356)
Brought to you by:
zzzeek
You can subscribe to this list here.
2006 |
Jan
|
Feb
(74) |
Mar
(167) |
Apr
(127) |
May
(190) |
Jun
(119) |
Jul
(77) |
Aug
(82) |
Sep
(84) |
Oct
(153) |
Nov
(45) |
Dec
(54) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(109) |
Feb
(80) |
Mar
(110) |
Apr
(106) |
May
(92) |
Jun
(147) |
Jul
(288) |
Aug
(307) |
Sep
(108) |
Oct
(156) |
Nov
(147) |
Dec
(134) |
2008 |
Jan
(126) |
Feb
(91) |
Mar
(184) |
Apr
(208) |
May
(212) |
Jun
(54) |
Jul
(106) |
Aug
(80) |
Sep
(58) |
Oct
(80) |
Nov
(119) |
Dec
(220) |
2009 |
Jan
(202) |
Feb
(50) |
Mar
(70) |
Apr
(46) |
May
(80) |
Jun
(61) |
Jul
(146) |
Aug
(81) |
Sep
(71) |
Oct
(74) |
Nov
(66) |
Dec
(82) |
2010 |
Jan
(112) |
Feb
(169) |
Mar
(235) |
Apr
(77) |
May
(22) |
Jun
(31) |
Jul
(46) |
Aug
(46) |
Sep
(70) |
Oct
(36) |
Nov
(37) |
Dec
(79) |
2011 |
Jan
(46) |
Feb
(54) |
Mar
(65) |
Apr
(73) |
May
(31) |
Jun
(46) |
Jul
(40) |
Aug
(36) |
Sep
(44) |
Oct
(33) |
Nov
(19) |
Dec
(10) |
2012 |
Jan
(60) |
Feb
(37) |
Mar
(35) |
Apr
(28) |
May
(27) |
Jun
(50) |
Jul
(33) |
Aug
(88) |
Sep
(64) |
Oct
(74) |
Nov
(62) |
Dec
(41) |
2013 |
Jan
(30) |
Feb
(37) |
Mar
(39) |
Apr
(52) |
May
(40) |
Jun
(85) |
Jul
(74) |
Aug
(76) |
Sep
(26) |
Oct
(76) |
Nov
(63) |
Dec
(65) |
2014 |
Jan
(68) |
Feb
(82) |
Mar
(87) |
Apr
(24) |
May
(66) |
Jun
(34) |
Jul
(86) |
Aug
(75) |
Sep
(70) |
Oct
(41) |
Nov
(23) |
Dec
(53) |
2015 |
Jan
(40) |
Feb
(39) |
Mar
(69) |
Apr
(64) |
May
(40) |
Jun
(43) |
Jul
(20) |
Aug
(48) |
Sep
(38) |
Oct
(28) |
Nov
(34) |
Dec
(44) |
2016 |
Jan
(82) |
Feb
(49) |
Mar
(25) |
Apr
(21) |
May
(19) |
Jun
(46) |
Jul
(38) |
Aug
(21) |
Sep
(33) |
Oct
(44) |
Nov
(26) |
Dec
(10) |
2017 |
Jan
(52) |
Feb
(18) |
Mar
(61) |
Apr
(43) |
May
(57) |
Jun
(36) |
Jul
(37) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
<!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>[1564] sqlalchemy/trunk/test: fixes half of [ticket:192], query.load()/get() with a unicode argument was failing to apply type conversion to the bind parameter</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1564</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-06-01 10:49:58 -0500 (Thu, 01 Jun 2006)</dd> </dl> <h3>Log Message</h3> <pre>fixes half of [ticket:192], query.load()/get() with a unicode argument was failing to apply type conversion to the bind parameter</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormquerypy">sqlalchemy/trunk/lib/sqlalchemy/orm/query.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyormquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/query.py (1563 => 1564)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/query.py 2006-06-01 15:20:35 UTC (rev 1563) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/query.py 2006-06-01 15:49:58 UTC (rev 1564) </span><span class="lines">@@ -24,7 +24,7 @@ </span><span class="cx"> if not hasattr(mapper, '_get_clause'): </span><span class="cx"> _get_clause = sql.and_() </span><span class="cx"> for primary_key in self.mapper.pks_by_table[self.table]: </span><del>- _get_clause.clauses.append(primary_key == sql.bindparam("pk_"+primary_key._label)) </del><ins>+ _get_clause.clauses.append(primary_key == sql.bindparam("pk_"+primary_key._label, type=primary_key.type)) </ins><span class="cx"> self.mapper._get_clause = _get_clause </span><span class="cx"> self._get_clause = self.mapper._get_clause </span><span class="cx"> def _get_session(self): </span></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1563 => 1564)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-06-01 15:20:35 UTC (rev 1563) +++ sqlalchemy/trunk/test/mapper.py 2006-06-01 15:49:58 UTC (rev 1564) </span><span class="lines">@@ -84,6 +84,22 @@ </span><span class="cx"> u2 = s.get(User, 7) </span><span class="cx"> self.assert_(u is not u2) </span><span class="cx"> </span><ins>+ def testunicodeget(self): + """tests that Query.get properly sets up the type for the bind parameter. using unicode would normally fail + on postgres, mysql and oracle unless it is converted to an encoded string""" + table = Table('foo', db, + Column('id', Unicode(10), primary_key=True), + Column('data', Unicode(40))) + try: + table.create() + class LocalFoo(object):pass + mapper(LocalFoo, table) + crit = 'petit voix m\xe2\x80\x99a '.decode('utf-8') + print repr(crit) + create_session().query(LocalFoo).get(crit) + finally: + table.drop() + </ins><span class="cx"> def testrefresh(self): </span><span class="cx"> mapper(User, users, properties={'addresses':relation(mapper(Address, addresses))}) </span><span class="cx"> s = create_session() </span></span></pre> </div> </div> </body> </html> |
<!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>[1563] sqlalchemy/trunk/lib/sqlalchemy/sql.py: "count" label changed to "rowcount", and default "count" argument is first pk col of the table or the first col if no pks</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1563</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-06-01 10:20:35 -0500 (Thu, 01 Jun 2006)</dd> </dl> <h3>Log Message</h3> <pre>"count" label changed to "rowcount", and default "count" argument is first pk col of the table or the first col if no pks</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1562 => 1563)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-06-01 02:03:36 UTC (rev 1562) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-06-01 15:20:35 UTC (rev 1563) </span><span class="lines">@@ -669,7 +669,11 @@ </span><span class="cx"> def accept_visitor(self, visitor): </span><span class="cx"> visitor.visit_fromclause(self) </span><span class="cx"> def count(self, whereclause=None, **params): </span><del>- return select([func.count(1).label('count')], whereclause, from_obj=[self], **params) </del><ins>+ if len(self.primary_key): + col = self.primary_key[0] + else: + col = list(self.columns)[0] + return select([func.count(col).label('rowcount')], whereclause, from_obj=[self], **params) </ins><span class="cx"> def join(self, right, *args, **kwargs): </span><span class="cx"> return Join(self, right, *args, **kwargs) </span><span class="cx"> def outerjoin(self, right, *args, **kwargs): </span><span class="lines">@@ -1248,7 +1252,11 @@ </span><span class="cx"> if asfrom: </span><span class="cx"> data[self] = self </span><span class="cx"> def count(self, whereclause=None, **params): </span><del>- return select([func.count(1).label('count')], whereclause, from_obj=[self], **params) </del><ins>+ if len(self.primary_key): + col = self.primary_key[0] + else: + col = list(self.columns)[0] + return select([func.count(col).label('rowcount')], whereclause, from_obj=[self], **params) </ins><span class="cx"> def join(self, right, *args, **kwargs): </span><span class="cx"> return Join(self, right, *args, **kwargs) </span><span class="cx"> def outerjoin(self, right, *args, **kwargs): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-06-01 02:03:46
|
<!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>[1562] sqlalchemy/trunk: implemented query string support in db urls, gets sent to dialect **kwargs, [ticket:196]</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1562</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 21:03:36 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>implemented query string support in db urls, gets sent to dialect **kwargs, [ticket:196]</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginestrategiespy">sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyengineurlpy">sqlalchemy/trunk/lib/sqlalchemy/engine/url.py</a></li> <li><a href="#sqlalchemytrunktestparseconnectpy">sqlalchemy/trunk/test/parseconnect.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1561 => 1562)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-06-01 01:18:00 UTC (rev 1561) +++ sqlalchemy/trunk/CHANGES 2006-06-01 02:03:36 UTC (rev 1562) </span><span class="lines">@@ -7,6 +7,8 @@ </span><span class="cx"> - fix to docs, removed incorrect info that close() is unsafe to use </span><span class="cx"> with threadlocal strategy (its totally safe !) </span><span class="cx"> - create_engine() can take URLs as string or unicode [ticket:188] </span><ins>+- firebird support ! thanks to James Ralston and Brad Clements for their +efforts. </ins><span class="cx"> </span><span class="cx"> 0.2.1 </span><span class="cx"> - "pool" argument to create_engine() properly propigates </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginestrategiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py (1561 => 1562)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-06-01 01:18:00 UTC (rev 1561) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-06-01 02:03:36 UTC (rev 1562) </span><span class="lines">@@ -29,7 +29,9 @@ </span><span class="cx"> u = url.make_url(name_or_url) </span><span class="cx"> module = u.get_module() </span><span class="cx"> </span><del>- dialect = module.dialect(**kwargs) </del><ins>+ args = u.query.copy() + args.update(kwargs) + dialect = module.dialect(**args) </ins><span class="cx"> </span><span class="cx"> poolargs = {} </span><span class="cx"> for key in (('echo_pool', 'echo'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </span><span class="lines">@@ -41,7 +43,7 @@ </span><span class="cx"> poolargs['use_threadlocal'] = False </span><span class="cx"> provider = default.PoolConnectionProvider(dialect, u, **poolargs) </span><span class="cx"> </span><del>- return base.ComposedSQLEngine(provider, dialect, **kwargs) </del><ins>+ return base.ComposedSQLEngine(provider, dialect, **args) </ins><span class="cx"> PlainEngineStrategy() </span><span class="cx"> </span><span class="cx"> class ThreadLocalEngineStrategy(EngineStrategy): </span><span class="lines">@@ -51,7 +53,9 @@ </span><span class="cx"> u = url.make_url(name_or_url) </span><span class="cx"> module = u.get_module() </span><span class="cx"> </span><del>- dialect = module.dialect(**kwargs) </del><ins>+ args = u.query.copy() + args.update(kwargs) + dialect = module.dialect(**args) </ins><span class="cx"> </span><span class="cx"> poolargs = {} </span><span class="cx"> for key in (('echo_pool', 'echo'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </span><span class="lines">@@ -63,7 +67,7 @@ </span><span class="cx"> poolargs['use_threadlocal'] = True </span><span class="cx"> provider = threadlocal.TLocalConnectionProvider(dialect, u, **poolargs) </span><span class="cx"> </span><del>- return threadlocal.TLEngine(provider, dialect, **kwargs) </del><ins>+ return threadlocal.TLEngine(provider, dialect, **args) </ins><span class="cx"> ThreadLocalEngineStrategy() </span><span class="cx"> </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyengineurlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/url.py (1561 => 1562)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-06-01 01:18:00 UTC (rev 1561) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-06-01 02:03:36 UTC (rev 1562) </span><span class="lines">@@ -3,13 +3,14 @@ </span><span class="cx"> import sqlalchemy.exceptions as exceptions </span><span class="cx"> </span><span class="cx"> class URL(object): </span><del>- def __init__(self, drivername, username=None, password=None, host=None, port=None, database=None): </del><ins>+ def __init__(self, drivername, username=None, password=None, host=None, port=None, database=None, query=None): </ins><span class="cx"> self.drivername = drivername </span><span class="cx"> self.username = username </span><span class="cx"> self.password = password </span><span class="cx"> self.host = host </span><span class="cx"> self.port = port </span><span class="cx"> self.database= database </span><ins>+ self.query = query or {} </ins><span class="cx"> def __str__(self): </span><span class="cx"> s = self.drivername + "://" </span><span class="cx"> if self.username is not None: </span><span class="lines">@@ -23,6 +24,10 @@ </span><span class="cx"> s += ':' + self.port </span><span class="cx"> if self.database is not None: </span><span class="cx"> s += '/' + self.database </span><ins>+ if len(self.query): + keys = self.query.keys() + keys.sort() + s += '?' + "&".join("%s=%s" % (k, self.query[k]) for k in keys) </ins><span class="cx"> return s </span><span class="cx"> def get_module(self): </span><span class="cx"> return getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername) </span><span class="lines">@@ -66,7 +71,13 @@ </span><span class="cx"> m = pattern.match(name) </span><span class="cx"> if m is not None: </span><span class="cx"> (name, username, password, host, port, database) = m.group(1, 2, 3, 4, 5, 6) </span><del>- opts = {'username':username,'password':password,'host':host,'port':port,'database':database} </del><ins>+ if database is not None: + tokens = database.split(r"?", 2) + database = tokens[0] + query = (len(tokens) > 1 and dict( cgi.parse_qsl(tokens[1]) ) or None) + else: + query = None + opts = {'username':username,'password':password,'host':host,'port':port,'database':database, 'query':query} </ins><span class="cx"> return URL(name, **opts) </span><span class="cx"> else: </span><span class="cx"> raise exceptions.ArgumentError("Could not parse rfc1738 URL from string '%s'" % name) </span></span></pre></div> <a id="sqlalchemytrunktestparseconnectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/parseconnect.py (1561 => 1562)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/parseconnect.py 2006-06-01 01:18:00 UTC (rev 1561) +++ sqlalchemy/trunk/test/parseconnect.py 2006-06-01 02:03:36 UTC (rev 1562) </span><span class="lines">@@ -13,10 +13,12 @@ </span><span class="cx"> 'dbtype://username:password@127.0.0.1:1521', </span><span class="cx"> 'dbtype://hostspec/database', </span><span class="cx"> 'dbtype://hostspec', </span><ins>+ 'dbtype://hostspec/?arg1=val1&arg2=val2', </ins><span class="cx"> 'dbtype:///database', </span><span class="cx"> 'dbtype:///:memory:', </span><span class="cx"> 'dbtype:///foo/bar/im/a/file', </span><span class="cx"> 'dbtype:///E:/work/src/LEM/db/hello.db', </span><ins>+ 'dbtype:///E:/work/src/LEM/db/hello.db?foo=bar&hoho=lala', </ins><span class="cx"> 'dbtype://', </span><span class="cx"> 'dbtype://username:password@/db' </span><span class="cx"> ): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-06-01 01:18:15
|
<!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>[1561] sqlalchemy/trunk/test: more test adjustments for firebird</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1561</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 20:18:00 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>more test adjustments for firebird</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestindexespy">sqlalchemy/trunk/test/indexes.py</a></li> <li><a href="#sqlalchemytrunktestselectresultspy">sqlalchemy/trunk/test/selectresults.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestindexespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/indexes.py (1560 => 1561)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/indexes.py 2006-06-01 01:12:39 UTC (rev 1560) +++ sqlalchemy/trunk/test/indexes.py 2006-06-01 01:18:00 UTC (rev 1561) </span><span class="lines">@@ -53,7 +53,7 @@ </span><span class="cx"> </span><span class="cx"> # Check that the table is useable. This is mostly for pg, </span><span class="cx"> # which can be somewhat sticky with mixed-case identifiers </span><del>- employees.insert().execute(firstName='Joe', lastName='Smith') </del><ins>+ employees.insert().execute(firstName='Joe', lastName='Smith', id=0) </ins><span class="cx"> ss = employees.select().execute().fetchall() </span><span class="cx"> assert ss[0].firstName == 'Joe' </span><span class="cx"> assert ss[0].lastName == 'Smith' </span></span></pre></div> <a id="sqlalchemytrunktestselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/selectresults.py (1560 => 1561)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/selectresults.py 2006-06-01 01:12:39 UTC (rev 1560) +++ sqlalchemy/trunk/test/selectresults.py 2006-06-01 01:18:00 UTC (rev 1561) </span><span class="lines">@@ -58,7 +58,7 @@ </span><span class="cx"> # this one fails in mysql as the result comes back as a string </span><span class="cx"> assert self.res.filter(foo.c.bar<30).sum(foo.c.bar) == 435 </span><span class="cx"> </span><del>- @testbase.unsupported('postgres', 'mysql') </del><ins>+ @testbase.unsupported('postgres', 'mysql', 'firebird') </ins><span class="cx"> def test_aggregate_2(self): </span><span class="cx"> # this one fails with postgres, the floating point comparison fails </span><span class="cx"> assert self.res.filter(foo.c.bar<30).avg(foo.c.bar) == 14.5 </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-06-01 01:12:50
|
<!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>[1560] sqlalchemy/trunk/test: brad clement's 0.2 firebird support !</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1560</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 20:12:39 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>brad clement's 0.2 firebird support !</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemydatabasesfirebirdpy">sqlalchemy/trunk/lib/sqlalchemy/databases/firebird.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> <li><a href="#sqlalchemytrunktestquerypy">sqlalchemy/trunk/test/query.py</a></li> <li><a href="#sqlalchemytrunktestreflectionpy">sqlalchemy/trunk/test/reflection.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemydatabasesfirebirdpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/databases/firebird.py (1559 => 1560)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/databases/firebird.py 2006-06-01 01:11:52 UTC (rev 1559) +++ sqlalchemy/trunk/lib/sqlalchemy/databases/firebird.py 2006-06-01 01:12:39 UTC (rev 1560) </span><span class="lines">@@ -7,17 +7,22 @@ </span><span class="cx"> </span><span class="cx"> import sys, StringIO, string </span><span class="cx"> </span><del>-import sqlalchemy.sql as sql </del><ins>+import sqlalchemy.engine.default as default +# import sqlalchemy.sql as sql </ins><span class="cx"> import sqlalchemy.schema as schema </span><span class="cx"> import sqlalchemy.ansisql as ansisql </span><del>-from sqlalchemy import * </del><ins>+# from sqlalchemy import * </ins><span class="cx"> import sqlalchemy.types as sqltypes </span><del>- </del><ins>+import sqlalchemy.exceptions as exceptions </ins><span class="cx"> try: </span><span class="cx"> import kinterbasdb </span><span class="cx"> except: </span><span class="cx"> kinterbasdb = None </span><span class="cx"> </span><ins>+dbmodule = kinterbasdb + +kinterbasdb.init(200) # fix this, init args should be passable via db_uri + </ins><span class="cx"> class FBNumeric(sqltypes.Numeric): </span><span class="cx"> def get_col_spec(self): </span><span class="cx"> return "NUMERIC(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length} </span><span class="lines">@@ -73,62 +78,92 @@ </span><span class="cx"> ('password', 'Password', None) </span><span class="cx"> ]} </span><span class="cx"> </span><del>-class FBSQLEngine(ansisql.ANSISQLEngine): - def __init__(self, opts, use_ansi = True, module = None, **params): - self._use_ansi = use_ansi - self.opts = opts or {} - if module is None: - self.module = kinterbasdb - else: - self.module = module - ansisql.ANSISQLEngine.__init__(self, **params) </del><ins>+class FireBirdExecutionContext(default.DefaultExecutionContext): + def supports_sane_rowcount(self): + return True + + def compiler(self, statement, bindparams, **kwargs): + return FBCompiler(statement, bindparams, **kwargs) </ins><span class="cx"> </span><del>- def do_commit(self, connection): - connection.commit(True) </del><ins>+ def schemagenerator(self, **params): + return FBSchemaGenerator(self, **params) + + def schemadropper(self, **params): + return FBSchemaDropper(self, **params) + + def defaultrunner(self, proxy): + return FBDefaultRunner(self, proxy) + +class FireBirdDialect(ansisql.ANSIDialect): + def __init__(self, module = None, **params): + self.module = module or dbmodule + self.opts = {} + ansisql.ANSIDialect.__init__(self, **params) </ins><span class="cx"> </span><del>- def do_rollback(self, connection): - connection.rollback(True) </del><ins>+ def create_connect_args(self, url): +# self.opts = url.translate_connect_args(['host', 'database', 'user', 'password']) + opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) + if opts.get('port'): + opts['host'] = "%s/%s" % (opts['host'], opts['port']) + del opts['port'] + self.opts = opts + + print "opts %r" % self.opts + return ([], self.opts) </ins><span class="cx"> </span><del>- def dbapi(self): - return self.module </del><ins>+ def connect_args(self): + return make_connect_string(self.opts) </ins><span class="cx"> </span><del>- def connect_args(self): - return [[], self.opts] - </del><ins>+ def create_execution_context(self): + return FireBirdExecutionContext(self) + </ins><span class="cx"> def type_descriptor(self, typeobj): </span><span class="cx"> return sqltypes.adapt_type(typeobj, colspecs) </span><span class="cx"> </span><del>- def last_inserted_ids(self): - return self.context.last_inserted_ids </del><ins>+ def supports_sane_rowcount(self): + return True </ins><span class="cx"> </span><span class="cx"> def compiler(self, statement, bindparams, **kwargs): </span><del>- return FBCompiler(statement, bindparams, engine=self, use_ansi=self._use_ansi, **kwargs) </del><ins>+ return FBCompiler(self, statement, bindparams, **kwargs) </ins><span class="cx"> </span><del>- def schemagenerator(self, **params): - return FBSchemaGenerator(self, **params) </del><ins>+ def schemagenerator(self, *args, **kwargs): + return FBSchemaGenerator(*args, **kwargs) + + def schemadropper(self, *args, **kwargs): + return FBSchemaDropper(*args, **kwargs) + + def defaultrunner(self, engine, proxy): + return FBDefaultRunner(engine, proxy) + + def has_table(self, connection, table_name): + tblqry = """\ + SELECT count(*) + FROM RDB$RELATION_FIELDS R + WHERE R.RDB$RELATION_NAME=?;""" </ins><span class="cx"> </span><del>- def schemadropper(self, **params): - return FBSchemaDropper(self, **params) - - def defaultrunner(self, proxy): - return FBDefaultRunner(self, proxy) - - def reflecttable(self, table): </del><ins>+ c = connection.execute(tblqry, [table_name.upper()]) + row = c.fetchone() + if row[0] > 0: + return True + else: + return False + + def reflecttable(self, connection, table): </ins><span class="cx"> #TODO: map these better </span><span class="cx"> column_func = { </span><del>- 14 : lambda r: String(r['FLEN']), # TEXT - 7 : lambda r: Integer(), # SHORT - 8 : lambda r: Integer(), # LONG - 9 : lambda r: Float(), # QUAD - 10 : lambda r: Float(), # FLOAT - 27 : lambda r: Double(), # DOUBLE - 35 : lambda r: DateTime(), # TIMESTAMP - 37 : lambda r: String(r['FLEN']), # VARYING - 261: lambda r: TEXT(), # BLOB - 40 : lambda r: Char(r['FLEN']), # CSTRING - 12 : lambda r: Date(), # DATE - 13 : lambda r: Time(), # TIME - 16 : lambda r: Numeric(precision=r['FPREC'], length=r['FSCALE'] * -1) #INT64 </del><ins>+ 14 : lambda r: sqltypes.String(r['FLEN']), # TEXT + 7 : lambda r: sqltypes.Integer(), # SHORT + 8 : lambda r: sqltypes.Integer(), # LONG + 9 : lambda r: sqltypes.Float(), # QUAD + 10 : lambda r: sqltypes.Float(), # FLOAT + 27 : lambda r: sqltypes.Double(), # DOUBLE + 35 : lambda r: sqltypes.DateTime(), # TIMESTAMP + 37 : lambda r: sqltypes.String(r['FLEN']), # VARYING + 261: lambda r: sqltypes.TEXT(), # BLOB + 40 : lambda r: sqltypes.Char(r['FLEN']), # CSTRING + 12 : lambda r: sqltypes.Date(), # DATE + 13 : lambda r: sqltypes.Time(), # TIME + 16 : lambda r: sqltypes.Numeric(precision=r['FPREC'], length=r['FSCALE'] * -1) #INT64 </ins><span class="cx"> } </span><span class="cx"> tblqry = """\ </span><span class="cx"> SELECT DISTINCT R.RDB$FIELD_NAME AS FNAME, </span><span class="lines">@@ -156,7 +191,7 @@ </span><span class="cx"> </span><span class="cx"> #import pdb;pdb.set_trace() </span><span class="cx"> # get all of the fields for this table </span><del>- c = self.execute(tblqry, [table.name.upper()]) </del><ins>+ c = connection.execute(tblqry, [table.name.upper()]) </ins><span class="cx"> while True: </span><span class="cx"> row = c.fetchone() </span><span class="cx"> if not row: break </span><span class="lines">@@ -168,40 +203,45 @@ </span><span class="cx"> # is it a foreign key (and what is it linked to) </span><span class="cx"> </span><span class="cx"> # is it a primary key? </span><del>- - table.append_item(Column(*args, **kw)) </del><ins>+ table.append_item(schema.Column(*args, **kw)) </ins><span class="cx"> # does the field have indexes </span><span class="cx"> </span><span class="cx"> def last_inserted_ids(self): </span><span class="cx"> return self.context.last_inserted_ids </span><ins>+ </ins><span class="cx"> </span><del>- def pre_exec(self, proxy, compiled, parameters, **kwargs): - pass - - def _executemany(self, c, statement, parameters): - rowcount = 0 - for param in parameters: - c.execute(statement, param) - rowcount += c.rowcount - self.context.rowcount = rowcount </del><ins>+ def do_execute(self, cursor, statement, parameters, **kwargs): + cursor.execute(statement, parameters or []) </ins><span class="cx"> </span><ins>+ def do_rollback(self, connection): + connection.rollback(True) + + def do_commit(self, connection): + connection.commit(True) + + def connection(self): + """returns a managed DBAPI connection from this SQLEngine's connection pool.""" + c = self._pool.connect() + c.supportsTransactions = 0 + return c + + + def dbapi(self): + return self.module + + </ins><span class="cx"> class FBCompiler(ansisql.ANSICompiler): </span><span class="cx"> """firebird compiler modifies the lexical structure of Select statements to work under </span><span class="cx"> non-ANSI configured Firebird databases, if the use_ansi flag is False.""" </span><span class="cx"> </span><del>- def __init__(self, engine, statement, parameters, use_ansi = True, **kwargs): </del><ins>+ def __init__(self, dialect, statement, parameters, **kwargs): </ins><span class="cx"> self._outertable = None </span><del>- self._use_ansi = use_ansi - ansisql.ANSICompiler.__init__(self, engine, statement, parameters, **kwargs) </del><ins>+ super(FBCompiler, self).__init__(dialect, statement, parameters, **kwargs) + </ins><span class="cx"> </span><span class="cx"> def visit_column(self, column): </span><del>- if self._use_ansi: - return ansisql.ANSICompiler.visit_column(self, column) </del><ins>+ return ansisql.ANSICompiler.visit_column(self, column) </ins><span class="cx"> </span><del>- if column.table is self._outertable: - self.strings[column] = "%s.%s(+)" % (column.table.name, column.name) - else: - self.strings[column] = "%s.%s" % (column.table.name, column.name) </del><span class="cx"> </span><span class="cx"> def visit_function(self, func): </span><span class="cx"> if len(func.clauses): </span><span class="lines">@@ -223,10 +263,11 @@ </span><span class="cx"> """ called when building a SELECT statment, position is just before column list </span><span class="cx"> Firebird puts the limit and offset right after the select...thanks for adding the </span><span class="cx"> visit_select_precolumns!!!""" </span><ins>+ result = "" + if select.limit: + result += " FIRST %d " % select.limit </ins><span class="cx"> if select.offset: </span><del>- result +=" FIRST " + select.offset - if select.limit: - result += " SKIP " + select.limit </del><ins>+ result +=" SKIP %d " % select.offset </ins><span class="cx"> if select.distinct: </span><span class="cx"> result += " DISTINCT " </span><span class="cx"> return result </span><span class="lines">@@ -269,3 +310,4 @@ </span><span class="cx"> return self.proxy("SELECT gen_id(" + seq.name + ", 1) FROM rdb$database").fetchone()[0] </span><span class="cx"> </span><span class="cx"> </span><ins>+dialect = FireBirdDialect </ins></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1559 => 1560)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-06-01 01:11:52 UTC (rev 1559) +++ sqlalchemy/trunk/test/mapper.py 2006-06-01 01:12:39 UTC (rev 1560) </span><span class="lines">@@ -245,6 +245,7 @@ </span><span class="cx"> # l = create_session().query(User).select(order_by=None) </span><span class="cx"> </span><span class="cx"> </span><ins>+ @testbase.unsupported('firebird') </ins><span class="cx"> def testfunction(self): </span><span class="cx"> """tests mapping to a SELECT statement that has functions in it.""" </span><span class="cx"> s = select([users, (users.c.user_id * 2).label('concat'), func.count(addresses.c.address_id).label('count')], </span><span class="lines">@@ -257,6 +258,7 @@ </span><span class="cx"> assert l[0].concat == l[0].user_id * 2 == 14 </span><span class="cx"> assert l[1].concat == l[1].user_id * 2 == 16 </span><span class="cx"> </span><ins>+ @testbase.unsupported('firebird') </ins><span class="cx"> def testcount(self): </span><span class="cx"> mapper(User, users) </span><span class="cx"> q = create_session().query(User) </span></span></pre></div> <a id="sqlalchemytrunktestquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/query.py (1559 => 1560)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/query.py 2006-06-01 01:11:52 UTC (rev 1559) +++ sqlalchemy/trunk/test/query.py 2006-06-01 01:12:39 UTC (rev 1560) </span><span class="lines">@@ -173,7 +173,7 @@ </span><span class="cx"> self.assertEqual(r.keys(), ['user_name', 'user_id']) </span><span class="cx"> self.assertEqual(r.values(), ['foo', 1]) </span><span class="cx"> </span><del>- @testbase.unsupported('oracle') </del><ins>+ @testbase.unsupported('oracle', 'firebird') </ins><span class="cx"> def test_column_accessor_shadow(self): </span><span class="cx"> shadowed = Table('test_shadowed', db, </span><span class="cx"> Column('shadow_id', INT, primary_key = True), </span></span></pre></div> <a id="sqlalchemytrunktestreflectionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/reflection.py (1559 => 1560)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/reflection.py 2006-06-01 01:11:52 UTC (rev 1559) +++ sqlalchemy/trunk/test/reflection.py 2006-06-01 01:12:39 UTC (rev 1560) </span><span class="lines">@@ -97,7 +97,7 @@ </span><span class="cx"> Column('multi_id', Integer, primary_key=True), </span><span class="cx"> Column('multi_rev', Integer, primary_key=True), </span><span class="cx"> Column('name', String(50), nullable=False), </span><del>- Column('value', String(100)) </del><ins>+ Column('val', String(100)) </ins><span class="cx"> ) </span><span class="cx"> table.create() </span><span class="cx"> # clear out table registry </span><span class="lines">@@ -114,9 +114,9 @@ </span><span class="cx"> ] </span><span class="cx"> ) </span><span class="cx"> table.create() </span><del>- table.insert().execute({'multi_id':1,'multi_rev':1,'name':'row1', 'value':'value1'}) - table.insert().execute({'multi_id':2,'multi_rev':18,'name':'row2', 'value':'value2'}) - table.insert().execute({'multi_id':3,'multi_rev':3,'name':'row3', 'value':'value3'}) </del><ins>+ table.insert().execute({'multi_id':1,'multi_rev':1,'name':'row1', 'val':'value1'}) + table.insert().execute({'multi_id':2,'multi_rev':18,'name':'row2', 'val':'value2'}) + table.insert().execute({'multi_id':3,'multi_rev':3,'name':'row3', 'val':'value3'}) </ins><span class="cx"> table.select().execute().fetchall() </span><span class="cx"> table.drop() </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-06-01 01:12:05
|
<!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>[1559] sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py: some comments...more to come</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1559</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 20:11:52 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>some comments...more to come</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 (1558 => 1559)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-31 16:15:10 UTC (rev 1558) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-06-01 01:11:52 UTC (rev 1559) </span><span class="lines">@@ -689,10 +689,19 @@ </span><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><span class="cx"> def _inheriting_tasks(self): </span><del>- """returns an iterator of UOWTasks whos mappers inherit from this UOWTask's mapper. Only - goes one level deep; i.e. for each UOWTask returned, you would call _inheriting_tasks on those - to get their inheriting tasks. For a multilevel-inheritance chain, i.e. A->B->C, and there are - UOWTasks for A and C but not B, C will be returned when this method is called on A, otherwise B.""" </del><ins>+ """returns a collection of UOWTasks whos mappers are immediate descendants of this UOWTask's mapper, + *or* are descendants of this UOWTask's mapper where the intervening anscestor mappers do not have + corresponding UOWTasks in the current UOWTransaction. + + Consider mapper A, which has descendant mappers B1 and B2. B1 has descendant mapper C1, B2 has descendant + mapper C2. UOWTasks are present for mappers A, B1, C1 and C2. + + A-> + B1->C1 + (B2)->C2 + + calling inheriting_tasks for A's UOWTask yields B1, C2. calling inheriting_tasks for B1's UOWTask yields C1. + """ </ins><span class="cx"> if self.circular_parent is not None: </span><span class="cx"> return </span><span class="cx"> def _tasks_by_mapper(mapper): </span><span class="lines">@@ -700,8 +709,6 @@ </span><span class="cx"> inherit_task = self.uowtransaction.tasks.get(m, None) </span><span class="cx"> if inherit_task is not None: </span><span class="cx"> yield inherit_task </span><del>- #for t in inherit_task._inheriting_tasks(): - # yield t </del><span class="cx"> else: </span><span class="cx"> for t in _tasks_by_mapper(m): </span><span class="cx"> yield t </span><span class="lines">@@ -710,6 +717,7 @@ </span><span class="cx"> inheriting_tasks = property(_inheriting_tasks) </span><span class="cx"> </span><span class="cx"> def polymorphic_tasks(self): </span><ins>+ """returns a collection of all UOWTasks whos mappers are descendants of this UOWTask's mapper.""" </ins><span class="cx"> yield self </span><span class="cx"> for task in self.inheriting_tasks: </span><span class="cx"> for t in task.polymorphic_tasks(): </span><span class="lines">@@ -720,7 +728,7 @@ </span><span class="cx"> return True </span><span class="cx"> if polymorphic: </span><span class="cx"> for task in self.inheriting_tasks: </span><del>- if task.contains_object(obj, True): </del><ins>+ if task.contains_object(obj, polymorphic=True): </ins><span class="cx"> return True </span><span class="cx"> return False </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-31 16:15:23
|
<!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>[1558] sqlalchemy/trunk: inherited synchronization behavior fixed to descend all the way to the base class</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1558</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 11:15:10 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>inherited synchronization behavior fixed to descend all the way to the base class</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormmapperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1557 => 1558)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-05-31 06:22:06 UTC (rev 1557) +++ sqlalchemy/trunk/CHANGES 2006-05-31 16:15:10 UTC (rev 1558) </span><span class="lines">@@ -1,6 +1,8 @@ </span><span class="cx"> 0.2.2 </span><span class="cx"> - big improvements to polymorphic inheritance behavior, enabling it </span><span class="cx"> to work with adjacency list table structures [ticket:190] </span><ins>+- major fixes and refactorings to inheritance relationships overall, +more unit tests </ins><span class="cx"> - fixed "echo_pool" flag on create_engine() </span><span class="cx"> - fix to docs, removed incorrect info that close() is unsafe to use </span><span class="cx"> with threadlocal strategy (its totally safe !) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1557 => 1558)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-31 06:22:06 UTC (rev 1557) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-31 16:15:10 UTC (rev 1558) </span><span class="lines">@@ -660,8 +660,16 @@ </span><span class="cx"> self._setattrbycolumn(obj, col, primary_key[i]) </span><span class="cx"> i+=1 </span><span class="cx"> self._postfetch(connection, table, obj, c, c.last_inserted_params()) </span><del>- if self._synchronizer is not None: - self._synchronizer.execute(obj, obj) </del><ins>+ + # synchronize newly inserted ids from one table to the next + def sync(mapper): + inherit = mapper.inherits + if inherit is not None: + sync(inherit) + if mapper._synchronizer is not None: + mapper._synchronizer.execute(obj, obj) + sync(self) + </ins><span class="cx"> self.extension.after_insert(self, connection, obj) </span><span class="cx"> </span><span class="cx"> def _postfetch(self, connection, table, obj, resultproxy, params): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-31 06:22:15
|
<!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>[1557] sqlalchemy/trunk/lib/sqlalchemy/orm: simplification/improvement to circular dependency sort (properly batches now)</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1557</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 01:22:06 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>simplification/improvement to circular dependency sort (properly batches now) mapper accepts add_property calls with columns that are not in its selectable (allows deferreds in, generally more lenient)</pre> <h3>Modified Paths</h3> <ul> <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="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1556 => 1557)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-31 06:19:56 UTC (rev 1556) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-31 06:22:06 UTC (rev 1557) </span><span class="lines">@@ -225,11 +225,7 @@ </span><span class="cx"> if not self.props.has_key(key): </span><span class="cx"> p = prop.copy() </span><span class="cx"> if p.adapt(self): </span><del>- # if we are "concrete", then its OK to skip columns from the parent - # not represented in our table (TODO: this should be refined to only skip the "polymorphic" column - # in the parent), otherwise we must be able to represent every column from the parent in our own - # selectable unit - self.add_property(key, p, init=False, skipmissing=concrete) </del><ins>+ self.add_property(key, p, init=False) </ins><span class="cx"> </span><span class="cx"> # load properties from the main table object, </span><span class="cx"> # not overriding those set up in the 'properties' argument </span><span class="lines">@@ -348,9 +344,9 @@ </span><span class="cx"> self.props[key] = prop </span><span class="cx"> </span><span class="cx"> if isinstance(prop, ColumnProperty): </span><del>- col = self.select_table.corresponding_column(prop.columns[0], keys_ok=True, raiseerr=not skipmissing) </del><ins>+ col = self.select_table.corresponding_column(prop.columns[0], keys_ok=True, raiseerr=False) </ins><span class="cx"> if col is None: </span><del>- return </del><ins>+ col = prop.columns[0] </ins><span class="cx"> self.columns[key] = col </span><span class="cx"> for col in prop.columns: </span><span class="cx"> proplist = self.columntoproperty.setdefault(col, []) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1556 => 1557)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-31 06:19:56 UTC (rev 1556) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-31 06:22:06 UTC (rev 1557) </span><span class="lines">@@ -338,6 +338,9 @@ </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><ins>+ # also convert to the "base mapper", the parentmost task at the top of an inheritance chain + # dependency sorting is done via non-inheriting mappers only, dependencies between mappers + # in the same inheritance chain is done at the per-object level </ins><span class="cx"> mapper = mapper.primary_mapper().base_mapper() </span><span class="cx"> dependency = dependency.primary_mapper().base_mapper() </span><span class="cx"> </span><span class="lines">@@ -758,8 +761,6 @@ </span><span class="cx"> # dependency processors that arent part of the cyclical thing </span><span class="cx"> # get put here </span><span class="cx"> extradeplist = [] </span><del>- - object_to_original_task = {} </del><span class="cx"> </span><span class="cx"> # organizes a set of new UOWTasks that will be assembled into </span><span class="cx"> # the final tree, for the purposes of holding new UOWDependencyProcessors </span><span class="lines">@@ -769,8 +770,7 @@ </span><span class="cx"> try: </span><span class="cx"> dp = dependencies[obj] </span><span class="cx"> except KeyError: </span><del>- dp = {} - dependencies[obj] = dp </del><ins>+ dp = dependencies.setdefault(obj, {}) </ins><span class="cx"> try: </span><span class="cx"> l = dp[depprocessor] </span><span class="cx"> except KeyError: </span><span class="lines">@@ -779,6 +779,7 @@ </span><span class="cx"> return l </span><span class="cx"> </span><span class="cx"> def dependency_in_cycles(dep): </span><ins>+ # TODO: make a simpler way to get at the "root inheritance" mapper </ins><span class="cx"> proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper().base_mapper(), True) </span><span class="cx"> targettask = trans.get_task_by_mapper(dep.targettask.mapper.base_mapper(), True) </span><span class="cx"> return targettask in cycles and (proctask is not None and proctask in cycles) </span><span class="lines">@@ -794,13 +795,14 @@ </span><span class="cx"> l = deps_by_targettask.setdefault(t, []) </span><span class="cx"> l.append(dep) </span><span class="cx"> </span><ins>+ object_to_original_task = {} + </ins><span class="cx"> for t in cycles: </span><span class="cx"> for task in t.polymorphic_tasks(): </span><span class="cx"> for taskelement in task.get_elements(polymorphic=False): </span><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><del>- </del><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><span class="lines">@@ -844,41 +846,24 @@ </span><span class="cx"> </span><span class="cx"> #print str(head) </span><span class="cx"> </span><del>- hierarchical_tasks = {} - def get_object_task(obj): - try: - return hierarchical_tasks[obj] - except KeyError: - originating_task = object_to_original_task[obj] - return hierarchical_tasks.setdefault(obj, UOWTask(self.uowtransaction, originating_task.mapper, circular_parent=self)) - - def make_task_tree(node, parenttask): - """takes a dependency-sorted tree of objects and creates a tree of UOWTasks""" </del><ins>+ # create a tree of UOWTasks corresponding to the tree of object instances + # created by the DependencySorter + def make_task_tree(node, parenttask, nexttasks): </ins><span class="cx"> #print "MAKETASKTREE", node.item, parenttask </span><del>- - t = get_object_task(node.item) - for n in node.children: - t2 = make_task_tree(n, t) - - # this flag is attempting to coalesce non-dependent operations into lists, instead of - # individual tasks, to produce more of a "batching" effect. great when it works, - # but easily breakable...so its at False for now - can_add_to_parent = False #parenttask.mapper._inherits(t.mapper) - - original_task = object_to_original_task[node.item] - #print "ORIG TASK", original_task - if original_task.contains_object(node.item, polymorphic=False): - if can_add_to_parent: - parenttask.append(node.item, original_task.objects[node.item].listonly, isdelete=original_task.objects[node.item].isdelete, childtask=t) - else: - t.append(node.item, original_task.objects[node.item].listonly, isdelete=original_task.objects[node.item].isdelete) - parenttask.append(None, listonly=False, isdelete=original_task.objects[node.item].isdelete, childtask=t) </del><ins>+ originating_task = object_to_original_task[node.item] + t = nexttasks.get(originating_task, None) + if t is None: + t = UOWTask(self.uowtransaction, originating_task.mapper, circular_parent=self) + nexttasks[originating_task] = t + parenttask.append(None, listonly=False, isdelete=originating_task.objects[node.item].isdelete, childtask=t) + t.append(node.item, originating_task.objects[node.item].listonly, isdelete=originating_task.objects[node.item].isdelete) + </ins><span class="cx"> if dependencies.has_key(node.item): </span><span class="cx"> for depprocessor, deptask in dependencies[node.item].iteritems(): </span><del>- if can_add_to_parent: - parenttask.cyclical_dependencies.add(depprocessor.branch(deptask)) - else: - t.cyclical_dependencies.add(depprocessor.branch(deptask)) </del><ins>+ t.cyclical_dependencies.add(depprocessor.branch(deptask)) + nd = {} + for n in node.children: + t2 = make_task_tree(n, t, nd) </ins><span class="cx"> return t </span><span class="cx"> </span><span class="cx"> # this is the new "circular" UOWTask which will execute in place of "self" </span><span class="lines">@@ -888,7 +873,7 @@ </span><span class="cx"> # circular UOWTask </span><span class="cx"> [t.dependencies.add(d) for d in extradeplist] </span><span class="cx"> t.childtasks = self.childtasks </span><del>- make_task_tree(head, t) </del><ins>+ make_task_tree(head, t, {}) </ins><span class="cx"> #print t.dump() </span><span class="cx"> return t </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-31 06:20:14
|
<!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>[1556] sqlalchemy/trunk/test/selectable.py: tweak to join test</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1556</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-31 01:19:56 -0500 (Wed, 31 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>tweak to join test</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestselectablepy">sqlalchemy/trunk/test/selectable.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestselectablepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/selectable.py (1555 => 1556)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/selectable.py 2006-05-30 23:36:19 UTC (rev 1555) +++ sqlalchemy/trunk/test/selectable.py 2006-05-31 06:19:56 UTC (rev 1556) </span><span class="lines">@@ -87,15 +87,10 @@ </span><span class="cx"> def testjoin(self): </span><span class="cx"> a = join(table, table2) </span><span class="cx"> print str(a.select(use_labels=True)) </span><del>- # TODO - figure out what we're trying to do here - return </del><span class="cx"> b = table2.alias('b') </span><span class="cx"> j = join(a, b) </span><span class="cx"> print str(j) </span><del>- return - criterion = a.c.col1 == b.c.col2 - print - print str(j) </del><ins>+ criterion = a.c.table1_col1 == b.c.col2 </ins><span class="cx"> self.assert_(criterion.compare(j.onclause)) </span><span class="cx"> </span><span class="cx"> def testselectalias(self): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-30 23:36:34
|
<!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>[1555] sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py: further tweaks to polymorphic loading...getting double polymorphic loaders to work</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1555</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-30 18:36:19 -0500 (Tue, 30 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>further tweaks to polymorphic loading...getting double polymorphic loaders to work</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormmapperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1554 => 1555)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-30 17:11:14 UTC (rev 1554) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-30 23:36:19 UTC (rev 1555) </span><span class="lines">@@ -154,12 +154,11 @@ </span><span class="cx"> if polymorphic_identity is not None: </span><span class="cx"> inherits.add_polymorphic_mapping(polymorphic_identity, self) </span><span class="cx"> self.polymorphic_identity = polymorphic_identity </span><del>- if self.polymorphic_on is None: - self.effective_polymorphic_on = inherits.effective_polymorphic_on - else: - self.effective_polymorphic_on = self.polymorphic_on </del><ins>+ if self.polymorphic_on is None and inherits.polymorphic_on is not None: + self.polymorphic_on = self.mapped_table.corresponding_column(inherits.polymorphic_on, keys_ok=True, raiseerr=False) </ins><span class="cx"> if self.order_by is False: </span><span class="cx"> self.order_by = inherits.order_by </span><ins>+ self.polymorphic_map = inherits.polymorphic_map </ins><span class="cx"> else: </span><span class="cx"> self._synchronizer = None </span><span class="cx"> self.inherits = None </span><span class="lines">@@ -167,7 +166,6 @@ </span><span class="cx"> if polymorphic_identity is not None: </span><span class="cx"> self.add_polymorphic_mapping(polymorphic_identity, self) </span><span class="cx"> self.polymorphic_identity = polymorphic_identity </span><del>- self.effective_polymorphic_on = self.polymorphic_on </del><span class="cx"> </span><span class="cx"> if select_table is not None: </span><span class="cx"> self.select_table = select_table </span><span class="lines">@@ -218,12 +216,20 @@ </span><span class="cx"> self.add_property(key, prop, False) </span><span class="cx"> </span><span class="cx"> if inherits is not None: </span><ins>+ # transfer properties from the inherited mapper to here. + # this includes column properties as well as relations. + # the column properties will attempt to be translated from the selectable unit + # of the parent mapper to this mapper's selectable unit. </ins><span class="cx"> inherits._inheriting_mappers.add(self) </span><span class="cx"> for key, prop in inherits.props.iteritems(): </span><span class="cx"> if not self.props.has_key(key): </span><span class="cx"> p = prop.copy() </span><span class="cx"> if p.adapt(self): </span><del>- self.add_property(key, p, init=False) </del><ins>+ # if we are "concrete", then its OK to skip columns from the parent + # not represented in our table (TODO: this should be refined to only skip the "polymorphic" column + # in the parent), otherwise we must be able to represent every column from the parent in our own + # selectable unit + self.add_property(key, p, init=False, skipmissing=concrete) </ins><span class="cx"> </span><span class="cx"> # load properties from the main table object, </span><span class="cx"> # not overriding those set up in the 'properties' argument </span><span class="lines">@@ -277,7 +283,7 @@ </span><span class="cx"> props[key] = self.select_table.corresponding_column(prop) </span><span class="cx"> elif (isinstance(prop, list) and sql.is_column(prop[0])): </span><span class="cx"> props[key] = [self.select_table.corresponding_column(c) for c in prop] </span><del>- self.__surrogate_mapper = Mapper(self.class_, self.select_table, non_primary=True, properties=props, polymorphic_map=self.polymorphic_map, polymorphic_on=self.polymorphic_on) </del><ins>+ self.__surrogate_mapper = Mapper(self.class_, self.select_table, non_primary=True, properties=props, polymorphic_map=self.polymorphic_map, polymorphic_on=self.select_table.corresponding_column(self.polymorphic_on)) </ins><span class="cx"> </span><span class="cx"> l = [(key, prop) for key, prop in self.props.iteritems()] </span><span class="cx"> for key, prop in l: </span><span class="lines">@@ -342,7 +348,10 @@ </span><span class="cx"> self.props[key] = prop </span><span class="cx"> </span><span class="cx"> if isinstance(prop, ColumnProperty): </span><del>- self.columns[key] = self.select_table.corresponding_column(prop.columns[0], keys_ok=True, raiseerr=True) </del><ins>+ col = self.select_table.corresponding_column(prop.columns[0], keys_ok=True, raiseerr=not skipmissing) + if col is None: + return + self.columns[key] = col </ins><span class="cx"> for col in prop.columns: </span><span class="cx"> proplist = self.columntoproperty.setdefault(col, []) </span><span class="cx"> proplist.append(prop) </span><span class="lines">@@ -585,7 +594,7 @@ </span><span class="cx"> value = self._getattrbycolumn(obj, col) </span><span class="cx"> if value is not None: </span><span class="cx"> params[col.key] = value </span><del>- elif self.effective_polymorphic_on is not None and self.effective_polymorphic_on.shares_lineage(col): </del><ins>+ elif self.polymorphic_on is not None and self.polymorphic_on.shares_lineage(col): </ins><span class="cx"> if isinsert: </span><span class="cx"> value = self.polymorphic_identity </span><span class="cx"> if col.default is None or value is not None: </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-30 17:11:31
|
<!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>[1554] sqlalchemy/trunk/test: further refinement of the polymorphic UOWTask idea.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1554</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-30 12:11:14 -0500 (Tue, 30 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>further refinement of the polymorphic UOWTask idea. circular dependency sort has to be pretty much focused on the base mappers of any inheritance chain, as it now takes part in pretty much any two dependent classes who share the same inherited parent.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormdependencypy">sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> <li><a href="#sqlalchemytrunktestinheritance2py">sqlalchemy/trunk/test/inheritance2.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 (1553 => 1554)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-29 22:41:30 UTC (rev 1553) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-30 17:11:14 UTC (rev 1554) </span><span class="lines">@@ -91,7 +91,7 @@ </span><span class="cx"> uowcommit.register_dependency(self.parent, self.mapper) </span><span class="cx"> uowcommit.register_processor(self.parent, self, self.parent) </span><span class="cx"> def process_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)) + " process_dep isdelete " + repr(delete) + " direction " + repr(self.direction) </ins><span class="cx"> if delete: </span><span class="cx"> # head object is being deleted, and we manage its list of child objects </span><span class="cx"> # the child objects have to have their foreign key to the parent set to NULL </span><span class="lines">@@ -121,7 +121,7 @@ </span><span class="cx"> self._synchronize(obj, child, None, 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)) + " preprocess_dep isdelete " + repr(delete) + " direction " + repr(self.direction) </ins><span class="cx"> </span><span class="cx"> if delete: </span><span class="cx"> # head object is being deleted, and we manage its list of child objects </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1553 => 1554)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-29 22:41:30 UTC (rev 1553) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-30 17:11:14 UTC (rev 1554) </span><span class="lines">@@ -324,6 +324,8 @@ </span><span class="cx"> this method returns or creates the single per-transaction instance of </span><span class="cx"> UOWTask that exists for that mapper.""" </span><span class="cx"> try: </span><ins>+ if isinstance(mapper, UOWTask): + raise "wha" </ins><span class="cx"> return self.tasks[mapper] </span><span class="cx"> except KeyError: </span><span class="cx"> if dontcreate: </span><span class="lines">@@ -363,6 +365,14 @@ </span><span class="cx"> self._mark_modified() </span><span class="cx"> </span><span class="cx"> def execute(self, echo=False): </span><ins>+ #print "\n------------------\nEXECUTE" + #for task in self.tasks.values(): + # print "\nTASK:", task + # for obj in task.objects: + # print "TASK OBJ:", obj + # for elem in task.get_elements(polymorphic=True): + # print "POLYMORPHIC TASK OBJ:", elem.obj + #print "-----------------------------" </ins><span class="cx"> # pre-execute dependency processors. this process may </span><span class="cx"> # result in new tasks, objects and/or dependency processors being added, </span><span class="cx"> # particularly with 'delete-orphan' cascade rules. </span><span class="lines">@@ -426,30 +436,24 @@ </span><span class="cx"> task.childtasks.append(t) </span><span class="cx"> return task </span><span class="cx"> </span><del>- mappers = sets.Set() - for task in self.tasks.values(): - mappers.add(task.mapper) - - 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) - mappers.remove(mapper) - - for task in self.tasks.values(): - inheriting_tasks(task) - </del><ins>+ mappers = self._get_noninheriting_mappers() </ins><span class="cx"> head = DependencySorter(self.dependencies, list(mappers)).sort(allow_all_cycles=True) </span><ins>+ #print "-------------------------" </ins><span class="cx"> #print str(head) </span><ins>+ #print "---------------------------" </ins><span class="cx"> task = sort_hier(head) </span><span class="cx"> return task </span><span class="cx"> </span><del>- </del><ins>+ def _get_noninheriting_mappers(self): + """returns a list of UOWTasks whose mappers are not inheriting from the mapper of another UOWTask. + i.e., this returns the root UOWTasks for all the inheritance hierarchies represented in this UOWTransaction.""" + mappers = sets.Set() + for task in self.tasks.values(): + base = task.mapper.base_mapper() + mappers.add(base) + return mappers + + </ins><span class="cx"> class UOWTaskElement(object): </span><span class="cx"> """an element within a UOWTask. corresponds to a single object instance </span><span class="cx"> to be saved, deleted, or just part of the transaction as a placeholder for </span><span class="lines">@@ -499,7 +503,6 @@ </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><span class="cx"> def __eq__(self, other): </span><span class="cx"> return other.processor is self.processor and other.targettask is self.targettask </span><span class="cx"> def __hash__(self): </span><span class="lines">@@ -512,7 +515,7 @@ </span><span class="cx"> def getobj(elem): </span><span class="cx"> elem.mark_preprocessed(self) </span><span class="cx"> return elem.obj </span><del>- </del><ins>+ </ins><span class="cx"> ret = False </span><span class="cx"> elements = [getobj(elem) for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)] </span><span class="cx"> if len(elements): </span><span class="lines">@@ -542,10 +545,10 @@ </span><span class="cx"> </span><span class="cx"> class UOWTask(object): </span><span class="cx"> """represents the full list of objects that are to be saved/deleted by a specific Mapper.""" </span><del>- def __init__(self, uowtransaction, mapper): - if uowtransaction is not None: </del><ins>+ def __init__(self, uowtransaction, mapper, circular_parent=None): + if not circular_parent: </ins><span class="cx"> uowtransaction.tasks[mapper] = self </span><del>- </del><ins>+ </ins><span class="cx"> # the transaction owning this UOWTask </span><span class="cx"> self.uowtransaction = uowtransaction </span><span class="cx"> </span><span class="lines">@@ -570,12 +573,16 @@ </span><span class="cx"> </span><span class="cx"> # a list of UOWTasks that correspond to Mappers which are inheriting </span><span class="cx"> # mappers of this UOWTask's Mapper </span><del>- self.inheriting_tasks = [] </del><ins>+ #self.inheriting_tasks = sets.Set() </ins><span class="cx"> </span><span class="cx"> # whether this UOWTask is circular, meaning it holds a second </span><del>- # UOWTask that contains a special row-based dependency structure </del><ins>+ # UOWTask that contains a special row-based dependency structure. </ins><span class="cx"> self.circular = None </span><span class="cx"> </span><ins>+ # for a task thats part of that row-based dependency structure, points + # back to the "public facing" task. + self.circular_parent = circular_parent + </ins><span class="cx"> # a list of UOWDependencyProcessors are derived from the main </span><span class="cx"> # set of dependencies, referencing sub-UOWTasks attached to this </span><span class="cx"> # one which represent portions of the total list of objects. </span><span class="lines">@@ -678,6 +685,27 @@ </span><span class="cx"> self._execute_per_element_childtasks(trans, True) </span><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><ins>+ def _inheriting_tasks(self): + """returns an iterator of UOWTasks whos mappers inherit from this UOWTask's mapper. Only + goes one level deep; i.e. for each UOWTask returned, you would call _inheriting_tasks on those + to get their inheriting tasks. For a multilevel-inheritance chain, i.e. A->B->C, and there are + UOWTasks for A and C but not B, C will be returned when this method is called on A, otherwise B.""" + if self.circular_parent is not None: + return + def _tasks_by_mapper(mapper): + for m in mapper._inheriting_mappers: + inherit_task = self.uowtransaction.tasks.get(m, None) + if inherit_task is not None: + yield inherit_task + #for t in inherit_task._inheriting_tasks(): + # yield t + else: + for t in _tasks_by_mapper(m): + yield t + for t in _tasks_by_mapper(self.mapper): + yield t + inheriting_tasks = property(_inheriting_tasks) + </ins><span class="cx"> def polymorphic_tasks(self): </span><span class="cx"> yield self </span><span class="cx"> for task in self.inheriting_tasks: </span><span class="lines">@@ -696,10 +724,10 @@ </span><span class="cx"> def get_elements(self, polymorphic=False): </span><span class="cx"> for rec in self.objects.values(): </span><span class="cx"> yield rec </span><del>- if polymorphic: - for task in self.inheriting_tasks: - for rec in task.get_elements(polymorphic=True): - 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><span class="cx"> polymorphic_tosave_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if not rec.isdelete]) </span><span class="cx"> polymorphic_todelete_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if rec.isdelete]) </span><span class="lines">@@ -746,13 +774,14 @@ </span><span class="cx"> try: </span><span class="cx"> l = dp[depprocessor] </span><span class="cx"> except KeyError: </span><del>- l = UOWTask(None, depprocessor.targettask.mapper) </del><ins>+ l = UOWTask(self.uowtransaction, depprocessor.targettask.mapper, circular_parent=self) </ins><span class="cx"> dp[depprocessor] = l </span><span class="cx"> return l </span><span class="cx"> </span><span class="cx"> def dependency_in_cycles(dep): </span><del>- proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper(), True) - return dep.targettask in cycles and (proctask is not None and proctask in cycles) </del><ins>+ proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper().base_mapper(), True) + targettask = trans.get_task_by_mapper(dep.targettask.mapper.base_mapper(), True) + return targettask in cycles and (proctask is not None and proctask in cycles) </ins><span class="cx"> </span><span class="cx"> # organize all original UOWDependencyProcessors by their target task </span><span class="cx"> deps_by_targettask = {} </span><span class="lines">@@ -775,8 +804,9 @@ </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>- #print "DEP iterate", dep.processor.key </del><ins>+ #print "DEP iterate", dep.processor.key, dep.processor.parent, dep.processor.mapper </ins><span class="cx"> if not dependency_in_cycles(dep): </span><ins>+ #print "NOT IN CYCLE" </ins><span class="cx"> continue </span><span class="cx"> #print "DEP", dep.processor.key </span><span class="cx"> (processor, targettask) = (dep.processor, dep.targettask) </span><span class="lines">@@ -820,7 +850,7 @@ </span><span class="cx"> return hierarchical_tasks[obj] </span><span class="cx"> except KeyError: </span><span class="cx"> originating_task = object_to_original_task[obj] </span><del>- return hierarchical_tasks.setdefault(obj, UOWTask(None, originating_task.mapper)) </del><ins>+ return hierarchical_tasks.setdefault(obj, UOWTask(self.uowtransaction, originating_task.mapper, circular_parent=self)) </ins><span class="cx"> </span><span class="cx"> def make_task_tree(node, parenttask): </span><span class="cx"> """takes a dependency-sorted tree of objects and creates a tree of UOWTasks""" </span><span class="lines">@@ -852,7 +882,7 @@ </span><span class="cx"> return t </span><span class="cx"> </span><span class="cx"> # this is the new "circular" UOWTask which will execute in place of "self" </span><del>- t = UOWTask(None, self.mapper) </del><ins>+ t = UOWTask(self.uowtransaction, self.mapper, circular_parent=self) </ins><span class="cx"> </span><span class="cx"> # stick the non-circular dependencies and child tasks onto the new </span><span class="cx"> # circular UOWTask </span></span></pre></div> <a id="sqlalchemytrunktestinheritance2py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/inheritance2.py (1553 => 1554)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/inheritance2.py 2006-05-29 22:41:30 UTC (rev 1553) +++ sqlalchemy/trunk/test/inheritance2.py 2006-05-30 17:11:14 UTC (rev 1554) </span><span class="lines">@@ -227,6 +227,57 @@ </span><span class="cx"> print orig </span><span class="cx"> print new </span><span class="cx"> assert orig == new == '<Assembly a1> specification=[<SpecLine 1.0 <Detail d1>>] documents=[<Document doc1>, <RasterDocument doc2>]' </span><ins>+ + def testfour(self): + """this tests the RasterDocument being attached to the Assembly, but *not* the Document. this means only + a "sub-class" task, i.e. corresponding to an inheriting mapper but not the base mapper, is created. """ + product_mapper = mapper(Product, products_table, + polymorphic_on=products_table.c.product_type, + polymorphic_identity='product') + detail_mapper = mapper(Detail, inherits=product_mapper, + polymorphic_identity='detail') + assembly_mapper = mapper(Assembly, inherits=product_mapper, + polymorphic_identity='assembly') + + document_mapper = mapper(Document, documents_table, + polymorphic_on=documents_table.c.document_type, + polymorphic_identity='document', + properties=dict( + name=documents_table.c.name, + data=deferred(documents_table.c.data), + product=relation(Product, lazy=True, backref='documents'), + ), + ) + raster_document_mapper = mapper(RasterDocument, inherits=document_mapper, + polymorphic_identity='raster_document') + + product_mapper.add_property('documents', + relation(Document, lazy=True, + backref='product', cascade='all, delete-orphan'), + ) + + session = create_session(echo_uow=False) + + a1 = Assembly(name='a1') + a1.documents.append(RasterDocument('doc2')) + session.save(a1) + orig = repr(a1) + session.flush() + session.clear() + + a1 = session.query(Product).get_by(name='a1') + new = repr(a1) + print orig + print new + assert orig == new == '<Assembly a1> specification=None documents=[<RasterDocument doc2>]' + + del a1.documents[0] + session.save(a1) + session.flush() + session.clear() + + a1 = session.query(Product).get_by(name='a1') + assert len(session.query(Document).select()) == 0 </ins><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span><span class="cx"> testbase.main() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 22:56: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>[1553] sqlalchemy/trunk: fixed [ticket:188] updated changelog</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1553</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 17:41:30 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>fixed [ticket:188] updated changelog</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyengineurlpy">sqlalchemy/trunk/lib/sqlalchemy/engine/url.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1552 => 1553)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-05-29 22:15:16 UTC (rev 1552) +++ sqlalchemy/trunk/CHANGES 2006-05-29 22:41:30 UTC (rev 1553) </span><span class="lines">@@ -1,3 +1,11 @@ </span><ins>+0.2.2 +- big improvements to polymorphic inheritance behavior, enabling it +to work with adjacency list table structures [ticket:190] +- fixed "echo_pool" flag on create_engine() +- fix to docs, removed incorrect info that close() is unsafe to use +with threadlocal strategy (its totally safe !) +- create_engine() can take URLs as string or unicode [ticket:188] + </ins><span class="cx"> 0.2.1 </span><span class="cx"> - "pool" argument to create_engine() properly propigates </span><span class="cx"> - fixes to URL, raises exception if not parsed, does not pass blank </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyengineurlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/url.py (1552 => 1553)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-29 22:15:16 UTC (rev 1552) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-29 22:41:30 UTC (rev 1553) </span><span class="lines">@@ -43,7 +43,7 @@ </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> def make_url(name_or_url): </span><del>- if isinstance(name_or_url, str): </del><ins>+ if isinstance(name_or_url, str) or isinstance(name_or_url, unicode): </ins><span class="cx"> return _parse_rfc1738_args(name_or_url) </span><span class="cx"> else: </span><span class="cx"> return name_or_url </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 22:15:29
|
<!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>[1552] sqlalchemy/trunk/test: polymorphic linked list test, tests polymorphic inheritance with circular refs</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1552</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 17:15:16 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>polymorphic linked list test, tests polymorphic inheritance with circular refs</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> <li><a href="#sqlalchemytrunktesttestbasepy">sqlalchemy/trunk/test/testbase.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunktestpoly_linked_listpy">sqlalchemy/trunk/test/poly_linked_list.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1551 => 1552)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-05-29 21:41:38 UTC (rev 1551) +++ sqlalchemy/trunk/test/alltests.py 2006-05-29 22:15:16 UTC (rev 1552) </span><span class="lines">@@ -44,6 +44,7 @@ </span><span class="cx"> </span><span class="cx"> # cyclical ORM persistence </span><span class="cx"> 'cycles', </span><ins>+ 'poly_linked_list', </ins><span class="cx"> </span><span class="cx"> # more select/persistence, backrefs </span><span class="cx"> 'entity', </span></span></pre></div> <a id="sqlalchemytrunktestpoly_linked_listpy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/test/poly_linked_list.py (1551 => 1552)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/poly_linked_list.py 2006-05-29 21:41:38 UTC (rev 1551) +++ sqlalchemy/trunk/test/poly_linked_list.py 2006-05-29 22:15:16 UTC (rev 1552) </span><span class="lines">@@ -0,0 +1,176 @@ </span><ins>+from sqlalchemy import * +import testbase + +class PolymorphicCircularTest(testbase.PersistTest): + def setUpAll(self): + global metadata + global Table1, Table1B, Table2, Table3, Data + metadata = BoundMetaData(testbase.db) + + table1 = Table('table1', metadata, + Column('id', Integer, primary_key=True), + Column('related_id', Integer, ForeignKey('table1.id'), nullable=True), + Column('type', String(30)), + Column('name', String(30)) + ) + + table2 = Table('table2', metadata, + Column('id', Integer, ForeignKey('table1.id'), primary_key=True), + ) + + table3 = Table('table3', metadata, + Column('id', Integer, ForeignKey('table1.id'), primary_key=True), + ) + + data = Table('data', metadata, + Column('id', Integer, primary_key=True), + Column('node_id', Integer, ForeignKey('table1.id')), + Column('data', String(30)) + ) + + metadata.create_all() + + join = polymorphic_union( + { + 'table3' : table1.join(table3), + 'table2' : table1.join(table2), + 'table1' : table1.select(table1.c.type.in_('table1', 'table1b')), + }, None, 'pjoin') + + # still with us so far ? + + class Table1(object): + def __init__(self, name, data=None): + self.name = name + if data is not None: + self.data = data + def __repr__(self): + return "%s(%d, %s, %s)" % (self.__class__.__name__, self.id, repr(str(self.name)), repr(self.data)) + + class Table1B(Table1): + pass + + class Table2(Table1): + pass + + class Table3(Table1): + pass + + class Data(object): + def __init__(self, data): + self.data = data + def __repr__(self): + return "%s(%d, %s)" % (self.__class__.__name__, self.id, repr(str(self.data))) + + # currently, all of these "eager" relationships degrade to lazy relationships + # due to the polymorphic load. + table1_mapper = mapper(Table1, table1, + select_table=join, + polymorphic_on=join.c.type, + polymorphic_identity='table1', + properties={ + 'next': relation(Table1, + backref=backref('prev', primaryjoin=join.c.id==join.c.related_id, foreignkey=join.c.id, uselist=False), + uselist=False, lazy=False, primaryjoin=join.c.id==join.c.related_id), + 'data':relation(mapper(Data, data), lazy=False) + } + ) + + table1b_mapper = mapper(Table1B, inherits=table1_mapper, polymorphic_identity='table1b') + + table2_mapper = mapper(Table2, table2, + inherits=table1_mapper, + polymorphic_identity='table2') + + table3_mapper = mapper(Table3, table3, inherits=table1_mapper, polymorphic_identity='table3') + def tearDown(self): + for t in metadata.table_iterator(reverse=True): + t.delete().execute() + + def tearDownAll(self): + clear_mappers() + metadata.drop_all() + + def testone(self): + self.do_testlist([Table1, Table2, Table1, Table2]) + + def testtwo(self): + self.do_testlist([Table3]) + + def testthree(self): + self.do_testlist([Table2, Table1, Table1B, Table3, Table3, Table1B, Table1B, Table2, Table1]) + + def testfour(self): + self.do_testlist([ + Table2('t2', [Data('data1'), Data('data2')]), + Table1('t1', []), + Table3('t3', [Data('data3')]), + Table1B('t1b', [Data('data4'), Data('data5')]) + ]) + + def do_testlist(self, classes): + sess = create_session(echo_uow=False) + + # create objects in a linked list + count = 1 + obj = None + for c in classes: + if isinstance(c, type): + newobj = c('item %d' % count) + count += 1 + else: + newobj = c + if obj is not None: + obj.next = newobj + else: + t = newobj + obj = newobj + + # save to DB + sess.save(t) + sess.flush() + + # string version of the saved list + assertlist = [] + node = t + while (node): + assertlist.append(node) + n = node.next + if n is not None: + assert n.prev is node + node = n + original = repr(assertlist) + + + # clear and query forwards + sess.clear() + node = sess.query(Table1).selectfirst(Table1.c.id==t.id) + assertlist = [] + while (node): + assertlist.append(node) + n = node.next + if n is not None: + assert n.prev is node + node = n + forwards = repr(assertlist) + + # clear and query backwards + sess.clear() + node = sess.query(Table1).selectfirst(Table1.c.id==obj.id) + assertlist = [] + while (node): + assertlist.insert(0, node) + n = node.prev + if n is not None: + assert n.next is node + node = n + backwards = repr(assertlist) + + # everything should match ! + print original + print backwards + print forwards + assert original == forwards == backwards + +if __name__ == '__main__': + testbase.main() </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunktesttestbasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/testbase.py (1551 => 1552)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/testbase.py 2006-05-29 21:41:38 UTC (rev 1551) +++ sqlalchemy/trunk/test/testbase.py 2006-05-29 22:15:16 UTC (rev 1552) </span><span class="lines">@@ -39,6 +39,7 @@ </span><span class="cx"> parser.add_option("--db", action="store", dest="db", default="sqlite", help="prefab database uri (sqlite, sqlite_file, postgres, mysql, oracle, oracle8, mssql)") </span><span class="cx"> parser.add_option("--mockpool", action="store_true", dest="mockpool", help="use mock pool") </span><span class="cx"> parser.add_option("--verbose", action="store_true", dest="verbose", help="full debug echoing") </span><ins>+ parser.add_option("--noecho", action="store_true", dest="noecho", help="Disable SQL statement echoing") </ins><span class="cx"> parser.add_option("--quiet", action="store_true", dest="quiet", help="be totally quiet") </span><span class="cx"> parser.add_option("--nothreadlocal", action="store_true", dest="nothreadlocal", help="dont use thread-local mod") </span><span class="cx"> parser.add_option("--enginestrategy", action="store", default=None, dest="enginestrategy", help="engine strategy (plain or threadlocal, defaults to SA default)") </span><span class="lines">@@ -86,9 +87,9 @@ </span><span class="cx"> if options.enginestrategy is not None: </span><span class="cx"> opts['strategy'] = options.enginestrategy </span><span class="cx"> if options.mockpool: </span><del>- db = engine.create_engine(db_uri, echo=True, default_ordering=True, poolclass=MockPool, **opts) </del><ins>+ db = engine.create_engine(db_uri, echo=(not options.noecho), default_ordering=True, poolclass=MockPool, **opts) </ins><span class="cx"> else: </span><del>- db = engine.create_engine(db_uri, echo=True, default_ordering=True, **opts) </del><ins>+ db = engine.create_engine(db_uri, echo=(not options.noecho), default_ordering=True, **opts) </ins><span class="cx"> db = EngineAssert(db) </span><span class="cx"> metadata = sqlalchemy.BoundMetaData(db) </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 21:41:50
|
<!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>[1551] sqlalchemy/trunk/test: unit-tested product/specline/etc stuff</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1551</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 16:41:38 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>unit-tested product/specline/etc stuff</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> <li><a href="#sqlalchemytrunktestinheritance2py">sqlalchemy/trunk/test/inheritance2.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1550 => 1551)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-05-29 17:21:41 UTC (rev 1550) +++ sqlalchemy/trunk/test/alltests.py 2006-05-29 21:41:38 UTC (rev 1551) </span><span class="lines">@@ -50,6 +50,7 @@ </span><span class="cx"> 'manytomany', </span><span class="cx"> 'onetoone', </span><span class="cx"> 'inheritance', </span><ins>+ 'inheritance2', </ins><span class="cx"> 'polymorph', </span><span class="cx"> </span><span class="cx"> # extensions </span></span></pre></div> <a id="sqlalchemytrunktestinheritance2py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/inheritance2.py (1550 => 1551)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/inheritance2.py 2006-05-29 17:21:41 UTC (rev 1550) +++ sqlalchemy/trunk/test/inheritance2.py 2006-05-29 21:41:38 UTC (rev 1551) </span><span class="lines">@@ -1,336 +1,232 @@ </span><del>-# UNDER CONSTRUCTION ! -# I am just pasting vladimir iliev's test cases here where they will be later assembled into unit tests. - </del><span class="cx"> from sqlalchemy import * </span><span class="cx"> from datetime import datetime </span><ins>+import testbase </ins><span class="cx"> </span><del>-metadata = BoundMetaData('sqlite://', echo=True) </del><ins>+class InheritTest(testbase.AssertMixin): + """tests some various inheritance round trips involving a particular set of polymorphic inheritance relationships""" + def setUpAll(self): + global metadata, products_table, specification_table, documents_table + global Product, Detail, Assembly, SpecLine, Document, RasterDocument + metadata = BoundMetaData(testbase.db) </ins><span class="cx"> </span><del>-products_table = Table('products', metadata, - Column('product_id', Integer, primary_key=True), - Column('product_type', String(128)), - Column('name', String(128)), - Column('mark', String(128)), - Column('material', String(128), default=''), - Column('sortament', String(128), default=''), - Column('weight', String(128), default=''), - ) </del><ins>+ products_table = Table('products', metadata, + Column('product_id', Integer, primary_key=True), + Column('product_type', String(128)), + Column('name', String(128)), + Column('mark', String(128)), + ) </ins><span class="cx"> </span><ins>+ specification_table = Table('specification', metadata, + Column('spec_line_id', Integer, primary_key=True), + Column('master_id', Integer, ForeignKey("products.product_id"), + nullable=True), + Column('slave_id', Integer, ForeignKey("products.product_id"), + nullable=True), + Column('quantity', Float, default=1.), + ) + + documents_table = Table('documents', metadata, + Column('document_id', Integer, primary_key=True), + Column('document_type', String(128)), + Column('product_id', Integer, ForeignKey('products.product_id')), + Column('create_date', DateTime, default=lambda:datetime.now()), + Column('last_updated', DateTime, default=lambda:datetime.now(), + onupdate=lambda:datetime.now()), + Column('name', String(128)), + Column('data', Binary), + Column('size', Integer, default=0), + ) + + metadata.create_all() </ins><span class="cx"> </span><del>-specification_table = Table('specification', metadata, - Column('spec_line_id', Integer, primary_key=True), - Column('master_id', Integer, ForeignKey("products.product_id"), - nullable=True), - Column('slave_id', Integer, ForeignKey("products.product_id"), - nullable=True), - Column('quantity', Float, default=1.), - ) </del><ins>+ class Product(object): + def __init__(self, name, mark=''): + self.name = name + self.mark = mark + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, self.name) </ins><span class="cx"> </span><ins>+ class Detail(Product): + def __init__(self, name): + self.name = name </ins><span class="cx"> </span><del>-class Product(object): </del><ins>+ class Assembly(Product): + def __repr__(self): + return Product.__repr__(self) + " " + " ".join([x + "=" + repr(getattr(self, x, None)) for x in ['specification', 'documents']]) </ins><span class="cx"> </span><del>- def __init__(self, name, mark=''): - self.name = name - self.mark = mark </del><ins>+ class SpecLine(object): + def __init__(self, master=None, slave=None, quantity=1): + self.master = master + self.slave = slave + self.quantity = quantity </ins><span class="cx"> </span><del>- def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.name) </del><ins>+ def __repr__(self): + return '<%s %.01f %s>' % ( + self.__class__.__name__, + self.quantity or 0., + repr(self.slave) + ) </ins><span class="cx"> </span><ins>+ class Document(object): + def __init__(self, name, data=None): + self.name = name + self.data = data + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, self.name) + + class RasterDocument(Document): + pass </ins><span class="cx"> </span><del>-class Detail(Product): </del><ins>+ def tearDown(self): + clear_mappers() + for t in metadata.table_iterator(reverse=True): + t.delete().execute() + + def tearDownAll(self): + metadata.drop_all() </ins><span class="cx"> </span><del>- def __init__(self, name, mark='', material='', sortament='', weight=''): - self.name = name - self.mark = mark - self.material = material - self.sortament = sortament - self.weight = weight </del><ins>+ def testone(self): + product_mapper = mapper(Product, products_table, + polymorphic_on=products_table.c.product_type, + polymorphic_identity='product') </ins><span class="cx"> </span><ins>+ detail_mapper = mapper(Detail, inherits=product_mapper, + polymorphic_identity='detail') </ins><span class="cx"> </span><del>-class Assembly(Product): pass </del><ins>+ assembly_mapper = mapper(Assembly, inherits=product_mapper, + polymorphic_identity='assembly') </ins><span class="cx"> </span><del>- -class SpecLine(object): - - def __init__(self, master=None, slave=None, quantity=1): - self.master = master - self.slave = slave - self.quantity = quantity - - def __repr__(self): - return '<%s %.01f %s>' % ( - self.__class__.__name__, - self.quantity or 0., - getattr(self.slave, 'name', None) </del><ins>+ specification_mapper = mapper(SpecLine, specification_table, + properties=dict( + master=relation(Assembly, + foreignkey=specification_table.c.master_id, + primaryjoin=specification_table.c.master_id==products_table.c.product_id, + lazy=True, backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), + uselist=False), + slave=relation(Product, + foreignkey=specification_table.c.slave_id, + primaryjoin=specification_table.c.slave_id==products_table.c.product_id, + lazy=True, uselist=False), + quantity=specification_table.c.quantity, + ) </ins><span class="cx"> ) </span><span class="cx"> </span><ins>+ session = create_session(echo_uow=False) </ins><span class="cx"> </span><ins>+ a1 = Assembly(name='a1') </ins><span class="cx"> </span><del>-product_mapper = mapper(Product, products_table, - polymorphic_on=products_table.c.product_type, - polymorphic_identity='product') </del><ins>+ p1 = Product(name='p1') + a1.specification.append(SpecLine(slave=p1)) </ins><span class="cx"> </span><del>-detail_mapper = mapper(Detail, inherits=product_mapper, - polymorphic_identity='detail') </del><ins>+ d1 = Detail(name='d1') + a1.specification.append(SpecLine(slave=d1)) </ins><span class="cx"> </span><del>-assembly_mapper = mapper(Assembly, inherits=product_mapper, - polymorphic_identity='assembly') </del><ins>+ session.save(a1) + orig = repr(a1) + session.flush() + session.clear() </ins><span class="cx"> </span><del>-specification_mapper = mapper(SpecLine, specification_table, - properties=dict( - master=relation(Assembly, - foreignkey=specification_table.c.master_id, - primaryjoin=specification_table.c.master_id==products_table.c.product_id, - lazy=True, backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), uselist=False), - slave=relation(Product, - foreignkey=specification_table.c.slave_id, - primaryjoin=specification_table.c.slave_id==products_table.c.product_id, - lazy=True, uselist=False), - quantity=specification_table.c.quantity, - ) - ) </del><ins>+ a1 = session.query(Product).get_by(name='a1') + new = repr(a1) + print orig + print new + assert orig == new == '<Assembly a1> specification=[<SpecLine 1.0 <Product p1>>, <SpecLine 1.0 <Detail d1>>] documents=None' </ins><span class="cx"> </span><ins>+ def testtwo(self): + product_mapper = mapper(Product, products_table, + polymorphic_on=products_table.c.product_type, + polymorphic_identity='product') </ins><span class="cx"> </span><del>-metadata.create_all() -session = create_session(echo_uow=True) </del><ins>+ detail_mapper = mapper(Detail, inherits=product_mapper, + polymorphic_identity='detail') </ins><span class="cx"> </span><ins>+ specification_mapper = mapper(SpecLine, specification_table, + properties=dict( + slave=relation(Product, + foreignkey=specification_table.c.slave_id, + primaryjoin=specification_table.c.slave_id==products_table.c.product_id, + lazy=True, uselist=False), + ) + ) </ins><span class="cx"> </span><del>-a1 = Assembly(name='a1') </del><ins>+ session = create_session(echo_uow=False) </ins><span class="cx"> </span><del>-p1 = Product(name='p1') -a1.specification.append(SpecLine(slave=p1)) </del><ins>+ s = SpecLine(slave=Product(name='p1')) + s2 = SpecLine(slave=Detail(name='d1')) + session.save(s) + session.save(s2) + orig = repr([s, s2]) + session.flush() + session.clear() + new = repr(session.query(SpecLine).select()) + print orig + print new + assert orig == new == '[<SpecLine 1.0 <Product p1>>, <SpecLine 1.0 <Detail d1>>]' </ins><span class="cx"> </span><del>-d1 = Detail(name='d1') -a1.specification.append(SpecLine(slave=d1)) </del><ins>+ def testthree(self): + product_mapper = mapper(Product, products_table, + polymorphic_on=products_table.c.product_type, + polymorphic_identity='product') + detail_mapper = mapper(Detail, inherits=product_mapper, + polymorphic_identity='detail') + assembly_mapper = mapper(Assembly, inherits=product_mapper, + polymorphic_identity='assembly') </ins><span class="cx"> </span><del>-session.save(a1) </del><ins>+ specification_mapper = mapper(SpecLine, specification_table, + properties=dict( + master=relation(Assembly, lazy=False, uselist=False, + foreignkey=specification_table.c.master_id, + primaryjoin=specification_table.c.master_id==products_table.c.product_id, + backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), + ), + slave=relation(Product, lazy=False, uselist=False, + foreignkey=specification_table.c.slave_id, + primaryjoin=specification_table.c.slave_id==products_table.c.product_id, + ), + quantity=specification_table.c.quantity, + ) + ) </ins><span class="cx"> </span><del>-session.flush() -session.clear() </del><ins>+ document_mapper = mapper(Document, documents_table, + polymorphic_on=documents_table.c.document_type, + polymorphic_identity='document', + properties=dict( + name=documents_table.c.name, + data=deferred(documents_table.c.data), + product=relation(Product, lazy=True, backref='documents'), + ), + ) + raster_document_mapper = mapper(RasterDocument, inherits=document_mapper, + polymorphic_identity='raster_document') </ins><span class="cx"> </span><del>-a1 = session.query(Product).get_by(name='a1') -print a1 -print a1.specification - -# ========================================================================================== - -from sqlalchemy import * - -metadata = BoundMetaData('sqlite://', echo=True) - -products_table = Table('products', metadata, - Column('product_id', Integer, primary_key=True), - Column('product_type', String(128)), - Column('name', String(128)), - ) - -specification_table = Table('specification', metadata, - Column('spec_line_id', Integer, primary_key=True), - Column('slave_id', Integer, ForeignKey("products.product_id"), - nullable=True), - ) - -class Product(object): - def __init__(self, name): - self.name = name - def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.name) - -class Detail(Product): - pass - -class SpecLine(object): - def __init__(self, slave=None): - self.slave = slave - def __repr__(self): - return '<%s %s>' % ( - self.__class__.__name__, - getattr(self.slave, 'name', None) </del><ins>+ assembly_mapper.add_property('specification', + relation(SpecLine, lazy=True, + primaryjoin=specification_table.c.master_id==products_table.c.product_id, + backref='master', cascade='all, delete-orphan', + ) </ins><span class="cx"> ) </span><span class="cx"> </span><del>-product_mapper = mapper(Product, products_table, - polymorphic_on=products_table.c.product_type, - polymorphic_identity='product') - -detail_mapper = mapper(Detail, inherits=product_mapper, - polymorphic_identity='detail') - -specification_mapper = mapper(SpecLine, specification_table, - properties=dict( - slave=relation(Product, - foreignkey=specification_table.c.slave_id, - primaryjoin=specification_table.c.slave_id==products_table.c.product_id, - lazy=True, uselist=False), - ) - ) - -metadata.create_all() -session = create_session(echo_uow=True) - -s = SpecLine(slave=Product(name='p1')) -s2 = SpecLine(slave=Detail(name='d1')) -session.save(s) -session.save(s2) -session.flush() -session.clear() -print session.query(SpecLine).select() - - -# ============================================================================================================================= - -from sqlalchemy import * -from datetime import datetime - - -metadata = BoundMetaData('sqlite:///', echo=False) - - -products_table = Table('products', metadata, - Column('product_id', Integer, primary_key=True), - Column('product_type', String(128)), - Column('name', String(128)), - Column('mark', String(128)), - Column('material', String(128), default=''), - Column('sortament', String(128), default=''), - Column('weight', String(128), default=''), - ) - - -specification_table = Table('specification', metadata, - Column('spec_line_id', Integer, primary_key=True), - Column('master_id', Integer, ForeignKey("products.product_id"), - nullable=True), - Column('slave_id', Integer, ForeignKey("products.product_id"), - nullable=True), - Column('quantity', Float, default=1.), - ) - - -documents_table = Table('documents', metadata, - Column('document_id', Integer, primary_key=True), - Column('document_type', String(128)), - Column('product_id', Integer, ForeignKey('products.product_id')), - Column('create_date', DateTime, default=lambda:datetime.now()), - Column('last_updated', DateTime, default=lambda:datetime.now(), - onupdate=lambda:datetime.now()), - Column('name', String(128)), - Column('data', Binary), - Column('size', Integer, default=0), - ) - -metadata.create_all() - - -class Product(object): - def __init__(self, name, mark=''): - self.name = name - self.mark = mark - def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.name) -class Detail(Product): - def __init__(self, name, mark='', material='', sortament='', weight=''): - self.name = name - self.mark = mark - self.material = material - self.sortament = sortament - self.weight = weight -class Assembly(Product): pass - - -class SpecLine(object): - - def __init__(self, master=None, slave=None, quantity=1): - self.master = master - self.slave = slave - self.quantity = quantity - - def __repr__(self): - return '<%s %.01f %s>' % ( - self.__class__.__name__, - self.quantity or 0., - getattr(self.slave, 'name', None) </del><ins>+ product_mapper.add_property('documents', + relation(Document, lazy=True, + backref='product', cascade='all, delete-orphan'), </ins><span class="cx"> ) </span><span class="cx"> </span><ins>+ session = create_session() </ins><span class="cx"> </span><del>-class Document(object): - def __init__(self, name, data=None): - self.name = name - self.data = data - def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, self.name) -class RasterDocument(Document): pass </del><ins>+ a1 = Assembly(name='a1') + a1.specification.append(SpecLine(slave=Detail(name='d1'))) + a1.documents.append(Document('doc1')) + a1.documents.append(RasterDocument('doc2')) + session.save(a1) + orig = repr(a1) + session.flush() + session.clear() </ins><span class="cx"> </span><del>- -product_mapper = mapper(Product, products_table, - polymorphic_on=products_table.c.product_type, - polymorphic_identity='product') -detail_mapper = mapper(Detail, inherits=product_mapper, - polymorphic_identity='detail') -assembly_mapper = mapper(Assembly, inherits=product_mapper, - polymorphic_identity='assembly') - - -specification_mapper = mapper(SpecLine, specification_table, - properties=dict( - master=relation(Assembly, lazy=False, uselist=False, - foreignkey=specification_table.c.master_id, - primaryjoin=specification_table.c.master_id==products_table.c.product_id, - backref=backref('specification', primaryjoin=specification_table.c.master_id==products_table.c.product_id), - ), - slave=relation(Product, lazy=False, uselist=False, - foreignkey=specification_table.c.slave_id, - primaryjoin=specification_table.c.slave_id==products_table.c.product_id, - ), - quantity=specification_table.c.quantity, - ) - ) - - -document_mapper = mapper(Document, documents_table, - polymorphic_on=documents_table.c.document_type, - polymorphic_identity='document', - properties=dict( - name=documents_table.c.name, - data=deferred(documents_table.c.data), - product=relation(Product, lazy=True, backref='documents'), - ), - ) -raster_document_mapper = mapper(RasterDocument, inherits=document_mapper, - polymorphic_identity='raster_document') - - -assembly_mapper.add_property('specification', - relation(SpecLine, lazy=True, - primaryjoin=specification_table.c.master_id==products_table.c.product_id, - backref='master', cascade='all, delete-orphan', - ) - ) - - -# bug #1 -# the property must be added to all the mapers individually, else delete-orphan doesnt work -for m in (product_mapper, assembly_mapper, detail_mapper): - m.add_property('documents', - relation(Document, lazy=True, - backref='product', cascade='all, delete-orphan'), - ) - - -session = create_session() - - -a1 = Assembly(name='a1') -a1.specification.append(SpecLine(slave=Detail(name='d1'))) -a1.documents.append(Document('doc1')) -a1.documents.append(RasterDocument('doc2')) # bug #2 -session.save(a1) -session.flush() -session.clear() -del a1 - - -a1 = session.query(Product).get_by(name='a1') -print a1.documents - - -# ============================================================================================================================== </del><span class="cx">\ No newline at end of file </span><ins>+ a1 = session.query(Product).get_by(name='a1') + new = repr(a1) + print orig + print new + assert orig == new == '<Assembly a1> specification=[<SpecLine 1.0 <Detail d1>>] documents=[<Document doc1>, <RasterDocument doc2>]' + +if __name__ == "__main__": + testbase.main() </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 17:21:58
|
<!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>[1550] sqlalchemy/trunk/doc/build/content: more polymorphic adjustments to circular dependency sort</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1550</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 12:21:41 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>more polymorphic adjustments to circular dependency sort</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentdbenginetxt">sqlalchemy/trunk/doc/build/content/dbengine.txt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormmapperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/orm/properties.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="sqlalchemytrunkdocbuildcontentdbenginetxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/dbengine.txt (1549 => 1550)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/dbengine.txt 2006-05-29 16:49:42 UTC (rev 1549) +++ sqlalchemy/trunk/doc/build/content/dbengine.txt 2006-05-29 17:21:41 UTC (rev 1550) </span><span class="lines">@@ -192,7 +192,7 @@ </span><span class="cx"> conn1 = db.contextual_connection() </span><span class="cx"> conn2 = db.contextual_connection() </span><span class="cx"> </span><del>- >>> assert conn1 is conn2 </del><ins>+ >>> assert conn1.connection is conn2.connection </ins><span class="cx"> True </span><span class="cx"> </span><span class="cx"> When the `plain` strategy is used, the `contextual_connection()` method is synonymous with the `connect()` method; both return a distinct connection from the pool. </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1549 => 1550)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-29 16:49:42 UTC (rev 1549) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-29 17:21:41 UTC (rev 1550) </span><span class="lines">@@ -231,7 +231,7 @@ </span><span class="cx"> if self.columntoproperty.has_key(column): </span><span class="cx"> continue </span><span class="cx"> if not self.columns.has_key(column.key): </span><del>- self.columns[column.key] = column </del><ins>+ self.columns[column.key] = self.select_table.corresponding_column(column, keys_ok=True, raiseerr=True) </ins><span class="cx"> </span><span class="cx"> prop = self.props.get(column.key, None) </span><span class="cx"> if prop is None: </span><span class="lines">@@ -291,7 +291,11 @@ </span><span class="cx"> return self.inherits.base_mapper() </span><span class="cx"> else: </span><span class="cx"> return self </span><del>- </del><ins>+ + def _inherits(self, mapper): + """returns True if the given mapper and this mapper are in the same inheritance hierarchy""" + return self.base_mapper() is mapper.base_mapper() + </ins><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="cx"> class_or_mapper = class_mapper(class_or_mapper, entity_name=entity_name) </span><span class="lines">@@ -338,7 +342,7 @@ </span><span class="cx"> self.props[key] = prop </span><span class="cx"> </span><span class="cx"> if isinstance(prop, ColumnProperty): </span><del>- self.columns[key] = prop.columns[0] </del><ins>+ self.columns[key] = self.select_table.corresponding_column(prop.columns[0], keys_ok=True, raiseerr=True) </ins><span class="cx"> for col in prop.columns: </span><span class="cx"> proplist = self.columntoproperty.setdefault(col, []) </span><span class="cx"> proplist.append(prop) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py (1549 => 1550)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-29 16:49:42 UTC (rev 1549) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-29 17:21:41 UTC (rev 1550) </span><span class="lines">@@ -150,12 +150,9 @@ </span><span class="cx"> </span><span class="cx"> private = property(lambda s:s.cascade.delete_orphan) </span><span class="cx"> </span><del>- def cascade_iterator(self, type, object, recursive=None): </del><ins>+ def cascade_iterator(self, type, object, recursive): </ins><span class="cx"> if not type in self.cascade: </span><span class="cx"> return </span><del>- if recursive is None: - recursive = sets.Set() - </del><span class="cx"> childlist = sessionlib.global_attributes.get_history(object, self.key, passive=True) </span><span class="cx"> </span><span class="cx"> for c in childlist.added_items() + childlist.deleted_items() + childlist.unchanged_items(): </span><span class="lines">@@ -163,7 +160,7 @@ </span><span class="cx"> if c not in recursive: </span><span class="cx"> recursive.add(c) </span><span class="cx"> yield c </span><del>- for c2 in self.mapper.cascade_iterator(type, c, recursive): </del><ins>+ for c2 in self.mapper.primary_mapper().cascade_iterator(type, c, recursive): </ins><span class="cx"> yield c2 </span><span class="cx"> </span><span class="cx"> def copy(self): </span><span class="lines">@@ -247,10 +244,9 @@ </span><span class="cx"> </span><span class="cx"> def _get_direction(self): </span><span class="cx"> """determines our 'direction', i.e. do we represent one to many, many to many, etc.""" </span><del>- </del><span class="cx"> if self.secondaryjoin is not None: </span><span class="cx"> return sync.MANYTOMANY </span><del>- elif self.parent.mapped_table is self.target: </del><ins>+ elif self.parent.mapped_table is self.target or self.parent.select_table is self.target: </ins><span class="cx"> if self.foreignkey.primary_key: </span><span class="cx"> return sync.MANYTOONE </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1549 => 1550)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-29 16:49:42 UTC (rev 1549) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-29 17:21:41 UTC (rev 1550) </span><span class="lines">@@ -761,8 +761,9 @@ </span><span class="cx"> for dep in task.dependencies: </span><span class="cx"> if not dependency_in_cycles(dep): </span><span class="cx"> extradeplist.append(dep) </span><del>- l = deps_by_targettask.setdefault(dep.targettask, []) - l.append(dep) </del><ins>+ for t in dep.targettask.polymorphic_tasks(): + l = deps_by_targettask.setdefault(t, []) + l.append(dep) </ins><span class="cx"> </span><span class="cx"> for t in cycles: </span><span class="cx"> for task in t.polymorphic_tasks(): </span><span class="lines">@@ -771,8 +772,10 @@ </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><ins>+ </ins><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><ins>+ #print "DEP iterate", dep.processor.key </ins><span class="cx"> if not dependency_in_cycles(dep): </span><span class="cx"> continue </span><span class="cx"> #print "DEP", dep.processor.key </span><span class="lines">@@ -790,8 +793,9 @@ </span><span class="cx"> for o in childlist: </span><span class="cx"> if o is None or not childtask.contains_object(o, polymorphic=True): </span><span class="cx"> continue </span><del>- #print "CHILD", o </del><ins>+ #print "parent/child", obj, o </ins><span class="cx"> whosdep = dep.whose_dependent_on_who(obj, o) </span><ins>+ #print "WHOSEDEP", dep.processor.key, dep.processor.direction, whosdep </ins><span class="cx"> if whosdep is not None: </span><span class="cx"> tuples.append(whosdep) </span><span class="cx"> # create a UOWDependencyProcessor representing this pair of objects. </span><span class="lines">@@ -820,13 +824,17 @@ </span><span class="cx"> </span><span class="cx"> def make_task_tree(node, parenttask): </span><span class="cx"> """takes a dependency-sorted tree of objects and creates a tree of UOWTasks""" </span><del>- #print "MAKETASKTREE", node.item </del><ins>+ #print "MAKETASKTREE", node.item, parenttask </ins><span class="cx"> </span><span class="cx"> t = get_object_task(node.item) </span><span class="cx"> for n in node.children: </span><span class="cx"> t2 = make_task_tree(n, t) </span><del>- - can_add_to_parent = t.mapper is parenttask.mapper </del><ins>+ + # this flag is attempting to coalesce non-dependent operations into lists, instead of + # individual tasks, to produce more of a "batching" effect. great when it works, + # but easily breakable...so its at False for now + can_add_to_parent = False #parenttask.mapper._inherits(t.mapper) + </ins><span class="cx"> original_task = object_to_original_task[node.item] </span><span class="cx"> #print "ORIG TASK", original_task </span><span class="cx"> if original_task.contains_object(node.item, polymorphic=False): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 16:49:54
|
<!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>[1549] sqlalchemy/trunk/doc/build/content: echo_pool flag fixed</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1549</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 11:49:42 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>echo_pool flag fixed removed incorrect paragraph regarding release modes</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentdbenginetxt">sqlalchemy/trunk/doc/build/content/dbengine.txt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginestrategiespy">sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentdbenginetxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/dbengine.txt (1548 => 1549)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/dbengine.txt 2006-05-29 05:17:21 UTC (rev 1548) +++ sqlalchemy/trunk/doc/build/content/dbengine.txt 2006-05-29 16:49:42 UTC (rev 1549) </span><span class="lines">@@ -181,8 +181,6 @@ </span><span class="cx"> # are returned to the pool. </span><span class="cx"> r2 = None </span><span class="cx"> </span><del>-While the `close()` method is still available with the "threadlocal" strategy, it should be used carefully. Above, if we issued a `close()` call on `r1`, and then tried to further work with results from `r2`, `r2` would be in an invalid state since its connection was already returned to the pool. By relying on `__del__()` to automatically clean up resources, this condition will never occur. - </del><span class="cx"> Advantages to `threadlocal` include that resources can be left to clean up after themselves, application code can be more minimal, its guaranteed that only one connection is used per thread, and there is no chance of a "connection pool block", which is when an execution hangs because the current thread has already checked out all remaining resources. </span><span class="cx"> </span><span class="cx"> To get at the actual `Connection` object which is used by implicit executions, call the `contextual_connection()` method on `Engine`: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginestrategiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py (1548 => 1549)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-29 05:17:21 UTC (rev 1548) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-29 16:49:42 UTC (rev 1549) </span><span class="lines">@@ -32,7 +32,7 @@ </span><span class="cx"> dialect = module.dialect(**kwargs) </span><span class="cx"> </span><span class="cx"> poolargs = {} </span><del>- for key in (('echo', 'echo_pool'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </del><ins>+ for key in (('echo_pool', 'echo'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </ins><span class="cx"> if kwargs.has_key(key[0]): </span><span class="cx"> poolargs[key[1]] = kwargs[key[0]] </span><span class="cx"> poolclass = getattr(module, 'poolclass', None) </span><span class="lines">@@ -54,7 +54,7 @@ </span><span class="cx"> dialect = module.dialect(**kwargs) </span><span class="cx"> </span><span class="cx"> poolargs = {} </span><del>- for key in (('echo', 'echo_pool'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </del><ins>+ for key in (('echo_pool', 'echo'), ('pool_size', 'pool_size'), ('max_overflow', 'max_overflow'), ('poolclass', 'poolclass'), ('pool_timeout','timeout'), ('pool', 'pool')): </ins><span class="cx"> if kwargs.has_key(key[0]): </span><span class="cx"> poolargs[key[1]] = kwargs[key[0]] </span><span class="cx"> poolclass = getattr(module, 'poolclass', None) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 05:17:38
|
<!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>[1548] sqlalchemy/trunk/lib/sqlalchemy/orm: working on [ticket:190], getting circular dependency sort to work with inheriting mappers</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1548</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-29 00:17:21 -0500 (Mon, 29 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>working on [ticket:190], getting circular dependency sort to work with inheriting mappers</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="#sqlalchemytrunklibsqlalchemyormpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/orm/properties.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 (1547 => 1548)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-29 03:24:24 UTC (rev 1547) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-29 05:17:21 UTC (rev 1548) </span><span class="lines">@@ -378,7 +378,7 @@ </span><span class="cx"> pass </span><span class="cx"> def delete_obj(self, *args, **kwargs): </span><span class="cx"> pass </span><del>- def _primary_mapper(self): </del><ins>+ def primary_mapper(self): </ins><span class="cx"> return self </span><span class="cx"> def base_mapper(self): </span><span class="cx"> return self </span><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 (1547 => 1548)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-29 03:24:24 UTC (rev 1547) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-29 05:17:21 UTC (rev 1548) </span><span class="lines">@@ -111,7 +111,7 @@ </span><span class="cx"> # tables - a collection of underlying Table objects pulled from mapped_table </span><span class="cx"> </span><span class="cx"> for table in (local_table, select_table): </span><del>- if table is not None and isinstance(local_table, sql.SelectBaseMixin): </del><ins>+ if table is not None and isinstance(table, sql.SelectBaseMixin): </ins><span class="cx"> # some db's, noteably postgres, dont want to select from a select </span><span class="cx"> # without an alias. also if we make our own alias internally, then </span><span class="cx"> # the configured properties on the mapper are not matched against the alias </span><span class="lines">@@ -174,6 +174,7 @@ </span><span class="cx"> else: </span><span class="cx"> self.select_table = self.mapped_table </span><span class="cx"> self.unjoined_table = self.local_table </span><ins>+ </ins><span class="cx"> </span><span class="cx"> # locate all tables contained within the "table" passed in, which </span><span class="cx"> # may be a join or other construct </span><span class="lines">@@ -265,11 +266,6 @@ </span><span class="cx"> if isinstance(self.polymorphic_map[key], type): </span><span class="cx"> self.polymorphic_map[key] = class_mapper(self.polymorphic_map[key]) </span><span class="cx"> </span><del>- l = [(key, prop) for key, prop in self.props.iteritems()] - for key, prop in l: - if getattr(prop, 'key', None) is None: - prop.init(key, self) - </del><span class="cx"> # select_table specified...set up a surrogate mapper that will be used for selects </span><span class="cx"> # select_table has to encompass all the columns of the mapped_table either directly </span><span class="cx"> # or through proxying relationships </span><span class="lines">@@ -279,9 +275,15 @@ </span><span class="cx"> for key, prop in properties.iteritems(): </span><span class="cx"> if sql.is_column(prop): </span><span class="cx"> props[key] = self.select_table.corresponding_column(prop) </span><del>- elif (isinstance(column, list) and sql.is_column(column[0])): </del><ins>+ elif (isinstance(prop, list) and sql.is_column(prop[0])): </ins><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>+ + l = [(key, prop) for key, prop in self.props.iteritems()] + for key, prop in l: + if getattr(prop, 'key', None) is None: + prop.init(key, self) + </ins><span class="cx"> </span><span class="cx"> def base_mapper(self): </span><span class="cx"> """returns the ultimate base mapper in an inheritance chain""" </span><span class="lines">@@ -356,7 +358,7 @@ </span><span class="cx"> """returns True if this mapper is the primary mapper for its class key (class + entity_name)""" </span><span class="cx"> return mapper_registry.get(self.class_key, None) is self </span><span class="cx"> </span><del>- def _primary_mapper(self): </del><ins>+ def primary_mapper(self): </ins><span class="cx"> """returns the primary mapper corresponding to this mapper's class key (class + entity_name)""" </span><span class="cx"> return mapper_registry[self.class_key] </span><span class="cx"> </span><span class="lines">@@ -514,8 +516,6 @@ </span><span class="cx"> def _setattrbycolumn(self, obj, column, value): </span><span class="cx"> self.columntoproperty[column][0].setattr(obj, value) </span><span class="cx"> </span><del>- def primary_mapper(self): - return mapper_registry[self.class_key] </del><span class="cx"> </span><span class="cx"> def save_obj(self, objects, uow, postupdate=False): </span><span class="cx"> """called by a UnitOfWork object to save objects, which involves either an INSERT or </span><span class="lines">@@ -1103,6 +1103,8 @@ </span><span class="cx"> self.selectable = selectable </span><span class="cx"> def __translate_col(self, col): </span><span class="cx"> ourcol = self.selectable.corresponding_column(col, keys_ok=False, raiseerr=False) </span><ins>+ #if col is not ourcol: + # print "TD TRANSLATING ", col, "TO", ourcol </ins><span class="cx"> if ourcol is None: </span><span class="cx"> return col </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py (1547 => 1548)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-29 03:24:24 UTC (rev 1547) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-29 05:17:21 UTC (rev 1548) </span><span class="lines">@@ -174,7 +174,7 @@ </span><span class="cx"> def do_init_subclass(self, key, parent): </span><span class="cx"> """template method for subclasses of PropertyLoader""" </span><span class="cx"> pass </span><del>- </del><ins>+ </ins><span class="cx"> def do_init(self, key, parent): </span><span class="cx"> import sqlalchemy.orm </span><span class="cx"> if isinstance(self.argument, type): </span><span class="lines">@@ -274,18 +274,18 @@ </span><span class="cx"> return </span><span class="cx"> if binary.left.primary_key: </span><span class="cx"> if dependent[0] is binary.left.table: </span><del>- raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (table '%s' appears on both sides of the relationship, or in an otherwise ambiguous manner). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), str(binary.left.table))) </del><ins>+ raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (table '%s' appears on both sides of the relationship, or in an otherwise ambiguous manner). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), binary.left.table.name)) </ins><span class="cx"> dependent[0] = binary.right.table </span><span class="cx"> self.foreignkey= binary.right </span><span class="cx"> elif binary.right.primary_key: </span><span class="cx"> if dependent[0] is binary.right.table: </span><del>- raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (table '%s' appears on both sides of the relationship, or in an otherwise ambiguous manner). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), str(binary.right.table))) </del><ins>+ raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (table '%s' appears on both sides of the relationship, or in an otherwise ambiguous manner). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), binary.right.table.name)) </ins><span class="cx"> dependent[0] = binary.left.table </span><span class="cx"> self.foreignkey = binary.left </span><span class="cx"> visitor = BinaryVisitor(foo) </span><span class="cx"> self.primaryjoin.accept_visitor(visitor) </span><span class="cx"> if dependent[0] is None: </span><del>- raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (no relationships joining tables '%s' and '%s' could be located). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), str(binary.left.table), str(binary.right.table))) </del><ins>+ raise exceptions.ArgumentError("Could not determine the parent/child relationship for property '%s', based on join condition '%s' (no relationships joining tables '%s' and '%s' could be located). please specify the 'foreignkey' keyword parameter to the relation() function indicating a column on the remote side of the relationship" % (self.key, str(self.primaryjoin), str(binary.left.table), binary.right.table.name)) </ins><span class="cx"> else: </span><span class="cx"> self.foreigntable = dependent[0] </span><span class="cx"> </span><span class="lines">@@ -637,7 +637,7 @@ </span><span class="cx"> PropertyLoader's mapper.""" </span><span class="cx"> # try to set a LazyLoader on our mapper referencing the parent mapper </span><span class="cx"> mapper = prop.mapper.primary_mapper() </span><del>- if not prop.mapper.props.has_key(self.key): </del><ins>+ if not mapper.props.has_key(self.key): </ins><span class="cx"> pj = self.kwargs.pop('primaryjoin', None) </span><span class="cx"> sj = self.kwargs.pop('secondaryjoin', None) </span><span class="cx"> # TODO: we are going to have the newly backref'd property create its </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1547 => 1548)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-29 03:24:24 UTC (rev 1547) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-29 05:17:21 UTC (rev 1548) </span><span class="lines">@@ -336,8 +336,8 @@ </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>- mapper = mapper._primary_mapper().base_mapper() - dependency = dependency._primary_mapper().base_mapper() </del><ins>+ mapper = mapper.primary_mapper().base_mapper() + dependency = dependency.primary_mapper().base_mapper() </ins><span class="cx"> </span><span class="cx"> self.dependencies[(mapper, dependency)] = True </span><span class="cx"> self._mark_modified() </span><span class="lines">@@ -353,8 +353,8 @@ </span><span class="cx"> #print "registerprocessor", str(mapper), repr(processor.key), str(mapperfrom) </span><span class="cx"> </span><span class="cx"> # correct for primary mapper (the mapper offcially associated with the class) </span><del>- mapper = mapper._primary_mapper() - mapperfrom = mapperfrom._primary_mapper() </del><ins>+ mapper = mapper.primary_mapper() + mapperfrom = mapperfrom.primary_mapper() </ins><span class="cx"> </span><span class="cx"> task = self.get_task_by_mapper(mapper) </span><span class="cx"> targettask = self.get_task_by_mapper(mapperfrom) </span><span class="lines">@@ -678,6 +678,12 @@ </span><span class="cx"> self._execute_per_element_childtasks(trans, True) </span><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><ins>+ def polymorphic_tasks(self): + yield self + for task in self.inheriting_tasks: + for t in task.polymorphic_tasks(): + yield t + </ins><span class="cx"> def contains_object(self, obj, polymorphic=False): </span><span class="cx"> if obj in self.objects: </span><span class="cx"> return True </span><span class="lines">@@ -745,55 +751,59 @@ </span><span class="cx"> return l </span><span class="cx"> </span><span class="cx"> def dependency_in_cycles(dep): </span><del>- proctask = trans.get_task_by_mapper(dep.processor.mapper, True) </del><ins>+ proctask = trans.get_task_by_mapper(dep.processor.mapper.primary_mapper(), True) </ins><span class="cx"> return dep.targettask in cycles and (proctask is not None and proctask in cycles) </span><span class="cx"> </span><span class="cx"> # organize all original UOWDependencyProcessors by their target task </span><span class="cx"> deps_by_targettask = {} </span><del>- for task in cycles: - for dep in task.dependencies: - if not dependency_in_cycles(dep): - extradeplist.append(dep) - l = deps_by_targettask.setdefault(dep.targettask, []) - l.append(dep) </del><ins>+ for t in cycles: + for task in t.polymorphic_tasks(): + for dep in task.dependencies: + if not dependency_in_cycles(dep): + extradeplist.append(dep) + l = deps_by_targettask.setdefault(dep.targettask, []) + l.append(dep) </ins><span class="cx"> </span><del>- for task in cycles: - for taskelement in task.get_elements(polymorphic=True): - obj = taskelement.obj - object_to_original_task[obj] = task - #print "OBJ", repr(obj), "TASK", repr(task) </del><ins>+ for t in cycles: + for task in t.polymorphic_tasks(): + for taskelement in task.get_elements(polymorphic=False): + obj = taskelement.obj + object_to_original_task[obj] = task + #print "OBJ", repr(obj), "TASK", repr(task) </ins><span class="cx"> </span><del>- for dep in deps_by_targettask.get(task, []): - # is this dependency involved in one of the cycles ? - if not dependency_in_cycles(dep): - continue - - (processor, targettask) = (dep.processor, dep.targettask) - isdelete = taskelement.isdelete </del><ins>+ for dep in deps_by_targettask.get(task, []): + # is this dependency involved in one of the cycles ? + if not dependency_in_cycles(dep): + continue + #print "DEP", dep.processor.key + (processor, targettask) = (dep.processor, dep.targettask) + isdelete = taskelement.isdelete </ins><span class="cx"> </span><del>- # list of dependent objects from this object - childlist = dep.get_object_dependencies(obj, trans, passive = True) </del><ins>+ # list of dependent objects from this object + childlist = dep.get_object_dependencies(obj, trans, passive = True) </ins><span class="cx"> </span><del>- # the task corresponding to saving/deleting of those dependent objects - childtask = trans.get_task_by_mapper(processor.mapper) </del><ins>+ # the task corresponding to saving/deleting of those dependent objects + childtask = trans.get_task_by_mapper(processor.mapper.primary_mapper()) </ins><span class="cx"> </span><del>- childlist = childlist.added_items() + childlist.unchanged_items() + childlist.deleted_items() </del><ins>+ childlist = childlist.added_items() + childlist.unchanged_items() + childlist.deleted_items() </ins><span class="cx"> </span><del>- for o in childlist: - if o is None or not childtask.contains_object(o, polymorphic=True): - continue - whosdep = dep.whose_dependent_on_who(obj, o) - if whosdep is not None: - tuples.append(whosdep) - # create a UOWDependencyProcessor representing this pair of objects. - # append it to a UOWTask - if whosdep[0] is obj: - get_dependency_task(whosdep[0], dep).append(whosdep[0], isdelete=isdelete) </del><ins>+ for o in childlist: + if o is None or not childtask.contains_object(o, polymorphic=True): + continue + #print "CHILD", o + whosdep = dep.whose_dependent_on_who(obj, o) + if whosdep is not None: + tuples.append(whosdep) + # create a UOWDependencyProcessor representing this pair of objects. + # append it to a UOWTask + if whosdep[0] is obj: + get_dependency_task(whosdep[0], dep).append(whosdep[0], isdelete=isdelete) + else: + get_dependency_task(whosdep[0], dep).append(whosdep[1], isdelete=isdelete) </ins><span class="cx"> else: </span><del>- get_dependency_task(whosdep[0], dep).append(whosdep[1], isdelete=isdelete) - else: - get_dependency_task(obj, dep).append(obj, isdelete=isdelete) - </del><ins>+ get_dependency_task(obj, dep).append(obj, isdelete=isdelete) + + #print "TUPLES", tuples </ins><span class="cx"> head = DependencySorter(tuples, allobjects).sort() </span><span class="cx"> if head is None: </span><span class="cx"> return None </span><span class="lines">@@ -818,6 +828,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><ins>+ #print "ORIG TASK", original_task </ins><span class="cx"> if original_task.contains_object(node.item, polymorphic=False): </span><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></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 03:24:35
|
<!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>[1547] sqlalchemy/tags/rel_0_2_1/: 0.2.1</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1547</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 22:24:24 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.2.1</pre> <h3>Added Paths</h3> <ul> <li>sqlalchemy/tags/rel_0_2_1/</li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytagsrel_0_2_1fromrev1546sqlalchemytrunk"></a> <div class="copfile"><h4>Copied: sqlalchemy/tags/rel_0_2_1 (from rev 1546, sqlalchemy/trunk) ( => )</h4> <pre class="diff"><span> <span class="info"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 03:14:21
|
<!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>[1546] sqlalchemy/trunk: 0.2.1 prep</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1546</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 22:14:11 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.2.1 prep</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunksetuppy">sqlalchemy/trunk/setup.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1545 => 1546)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-05-29 02:57:33 UTC (rev 1545) +++ sqlalchemy/trunk/CHANGES 2006-05-29 03:14:11 UTC (rev 1546) </span><span class="lines">@@ -1,3 +1,27 @@ </span><ins>+0.2.1 +- "pool" argument to create_engine() properly propigates +- fixes to URL, raises exception if not parsed, does not pass blank +fields along to the DB connect string (a string such as +user:host@/db was breaking on postgres) +- small fixes to Mapper when it inserts and tries to get +new primary key values back +- rewrote half of TLEngine, the ComposedSQLEngine used with +'strategy="threadlocal"'. it now properly implements engine.begin()/ +engine.commit(), which nest fully with connection.begin()/trans.commit(). +added about six unittests. +- major "duh" in pool.Pool, forgot to put back the WeakValueDictionary. +unittest which was supposed to check for this was also silently missing +it. fixed unittest to insure that ConnectionFairy properly falls out +of scope. +- placeholder dispose() method added to SingletonThreadPool, doesnt +do anything yet +- rollback() is automatically called when an exception is raised, +but only if theres no transaction in process (i.e. works more like +autocommit). +- fixed exception raise in sqlite if no sqlite module present +- added extra example detail for association object doc +- Connection adds checks for already being closed + </ins><span class="cx"> 0.2.0 </span><span class="cx"> - overhaul to Engine system so that what was formerly the SQLEngine </span><span class="cx"> is now a ComposedSQLEngine which consists of a variety of components, </span></span></pre></div> <a id="sqlalchemytrunksetuppy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/setup.py (1545 => 1546)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/setup.py 2006-05-29 02:57:33 UTC (rev 1545) +++ sqlalchemy/trunk/setup.py 2006-05-29 03:14:11 UTC (rev 1546) </span><span class="lines">@@ -3,7 +3,7 @@ </span><span class="cx"> from setuptools import setup, find_packages </span><span class="cx"> </span><span class="cx"> setup(name = "SQLAlchemy", </span><del>- version = "0.2.0", </del><ins>+ version = "0.2.1", </ins><span class="cx"> description = "Database Abstraction Library", </span><span class="cx"> author = "Mike Bayer", </span><span class="cx"> author_email = "mi...@zz...", </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 02:57:43
|
<!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>[1545] sqlalchemy/trunk/test: connection more careful about checking if its closed before operations</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1545</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 21:57:33 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>connection more careful about checking if its closed before operations small fix to table sort if no tables unit test tweaks</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginebasepy">sqlalchemy/trunk/lib/sqlalchemy/engine/base.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemysql_utilpy">sqlalchemy/trunk/lib/sqlalchemy/sql_util.py</a></li> <li><a href="#sqlalchemytrunktestdefaultspy">sqlalchemy/trunk/test/defaults.py</a></li> <li><a href="#sqlalchemytrunktesttransactionpy">sqlalchemy/trunk/test/transaction.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginebasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/base.py (1544 => 1545)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-29 02:33:03 UTC (rev 1544) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-29 02:57:33 UTC (rev 1545) </span><span class="lines">@@ -177,8 +177,13 @@ </span><span class="cx"> self.__connection = connection or engine.raw_connection() </span><span class="cx"> self.__transaction = None </span><span class="cx"> self.__close_with_result = close_with_result </span><ins>+ def _get_connection(self): + try: + return self.__connection + except AttributeError: + raise exceptions.InvalidRequestError("This Connection is closed") </ins><span class="cx"> engine = property(lambda s:s.__engine, doc="The Engine with which this Connection is associated (read only)") </span><del>- connection = property(lambda s:s.__connection, doc="The underlying DBAPI connection managed by this Connection.") </del><ins>+ connection = property(_get_connection, doc="The underlying DBAPI connection managed by this Connection.") </ins><span class="cx"> should_close_with_result = property(lambda s:s.__close_with_result, doc="Indicates if this Connection should be closed when a corresponding ResultProxy is closed; this is essentially an auto-release mode.") </span><span class="cx"> def _create_transaction(self, parent): </span><span class="cx"> return Transaction(self, parent) </span><span class="lines">@@ -199,15 +204,15 @@ </span><span class="cx"> def _begin_impl(self): </span><span class="cx"> if self.__engine.echo: </span><span class="cx"> self.__engine.log("BEGIN") </span><del>- self.__engine.dialect.do_begin(self.__connection) </del><ins>+ self.__engine.dialect.do_begin(self.connection) </ins><span class="cx"> def _rollback_impl(self): </span><span class="cx"> if self.__engine.echo: </span><span class="cx"> self.__engine.log("ROLLBACK") </span><del>- self.__engine.dialect.do_rollback(self.__connection) </del><ins>+ self.__engine.dialect.do_rollback(self.connection) </ins><span class="cx"> def _commit_impl(self): </span><span class="cx"> if self.__engine.echo: </span><span class="cx"> self.__engine.log("COMMIT") </span><del>- self.__engine.dialect.do_commit(self.__connection) </del><ins>+ self.__engine.dialect.do_commit(self.connection) </ins><span class="cx"> def _autocommit(self, statement): </span><span class="cx"> """when no Transaction is present, this is called after executions to provide "autocommit" behavior.""" </span><span class="cx"> # TODO: have the dialect determine if autocommit can be set on the connection directly without this </span><span class="lines">@@ -218,9 +223,13 @@ </span><span class="cx"> if not self.in_transaction(): </span><span class="cx"> self._rollback_impl() </span><span class="cx"> def close(self): </span><del>- if self.__connection is not None: - self.__connection.close() - self.__connection = None </del><ins>+ try: + c = self.__connection + except AttributeError: + return + self.__connection.close() + self.__connection = None + del self.__connection </ins><span class="cx"> def scalar(self, object, parameters=None, **kwargs): </span><span class="cx"> row = self.execute(object, parameters, **kwargs).fetchone() </span><span class="cx"> if row is not None: </span><span class="lines">@@ -255,7 +264,7 @@ </span><span class="cx"> return self.execute_compiled(elem.compile(engine=self.__engine, parameters=param), *multiparams, **params) </span><span class="cx"> def execute_compiled(self, compiled, *multiparams, **params): </span><span class="cx"> """executes a sql.Compiled object.""" </span><del>- cursor = self.__connection.cursor() </del><ins>+ cursor = self.connection.cursor() </ins><span class="cx"> parameters = [compiled.get_params(**m) for m in self._params_to_listofdicts(*multiparams, **params)] </span><span class="cx"> if len(parameters) == 1: </span><span class="cx"> parameters = parameters[0] </span><span class="lines">@@ -295,7 +304,7 @@ </span><span class="cx"> callable_(self) </span><span class="cx"> def _execute_raw(self, statement, parameters=None, cursor=None, echo=None, context=None, **kwargs): </span><span class="cx"> if cursor is None: </span><del>- cursor = self.__connection.cursor() </del><ins>+ cursor = self.connection.cursor() </ins><span class="cx"> try: </span><span class="cx"> if echo is True or self.__engine.echo is not False: </span><span class="cx"> self.__engine.log(statement) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemysql_utilpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql_util.py (1544 => 1545)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql_util.py 2006-05-29 02:33:03 UTC (rev 1544) +++ sqlalchemy/trunk/lib/sqlalchemy/sql_util.py 2006-05-29 02:57:33 UTC (rev 1545) </span><span class="lines">@@ -27,7 +27,8 @@ </span><span class="cx"> seq.append( node.item ) </span><span class="cx"> for child in node.children: </span><span class="cx"> to_sequence( child ) </span><del>- to_sequence( head ) </del><ins>+ if head is not None: + to_sequence( head ) </ins><span class="cx"> if reverse: </span><span class="cx"> sequence.reverse() </span><span class="cx"> return sequence </span></span></pre></div> <a id="sqlalchemytrunktestdefaultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/defaults.py (1544 => 1545)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/defaults.py 2006-05-29 02:33:03 UTC (rev 1544) +++ sqlalchemy/trunk/test/defaults.py 2006-05-29 02:57:33 UTC (rev 1545) </span><span class="lines">@@ -165,4 +165,4 @@ </span><span class="cx"> cartitems.drop() </span><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span><del>- unittest.main() </del><ins>+ testbase.main() </ins></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1544 => 1545)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-29 02:33:03 UTC (rev 1544) +++ sqlalchemy/trunk/test/transaction.py 2006-05-29 02:57:33 UTC (rev 1545) </span><span class="lines">@@ -35,6 +35,7 @@ </span><span class="cx"> assert len(result.fetchall()) == 0 </span><span class="cx"> connection.close() </span><span class="cx"> </span><ins>+ @testbase.unsupported('mysql') </ins><span class="cx"> def testnesting(self): </span><span class="cx"> connection = testbase.db.connect() </span><span class="cx"> transaction = connection.begin() </span><span class="lines">@@ -59,7 +60,8 @@ </span><span class="cx"> </span><span class="cx"> def tearDownAll(self): </span><span class="cx"> metadata.drop_all(testbase.db) </span><del>- </del><ins>+ + @testbase.unsupported('sqlite') </ins><span class="cx"> def testrollback_deadlock(self): </span><span class="cx"> """test that returning connections to the pool clears any object locks.""" </span><span class="cx"> conn1 = testbase.db.connect() </span><span class="lines">@@ -144,6 +146,7 @@ </span><span class="cx"> finally: </span><span class="cx"> external_connection.close() </span><span class="cx"> </span><ins>+ @testbase.unsupported('mysql') </ins><span class="cx"> def testmixednesting(self): </span><span class="cx"> """tests nesting of transactions off the TLEngine directly inside of </span><span class="cx"> tranasctions off the connection from the TLEngine""" </span><span class="lines">@@ -172,6 +175,7 @@ </span><span class="cx"> finally: </span><span class="cx"> external_connection.close() </span><span class="cx"> </span><ins>+ @testbase.unsupported('mysql') </ins><span class="cx"> def testmoremixednesting(self): </span><span class="cx"> """tests nesting of transactions off the connection from the TLEngine </span><span class="cx"> inside of tranasctions off thbe TLEngine directly.""" </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 02:33:14
|
<!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>[1544] sqlalchemy/trunk/doc/build/content: added extra info for association object</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1544</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 21:33:03 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>added extra info for association object threadlocal transaction benefits from an explicit close() on the connection besides de-referencing it</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentdatamappingtxt">sqlalchemy/trunk/doc/build/content/datamapping.txt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginethreadlocalpy">sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentdatamappingtxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/datamapping.txt (1543 => 1544)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/datamapping.txt 2006-05-29 02:12:53 UTC (rev 1543) +++ sqlalchemy/trunk/doc/build/content/datamapping.txt 2006-05-29 02:33:03 UTC (rev 1544) </span><span class="lines">@@ -785,3 +785,26 @@ </span><span class="cx"> for k in a.keywords: </span><span class="cx"> if k.keyword.name == 'jacks_stories': </span><span class="cx"> print k.user.user_name </span><ins>+ +Keep in mind that the association object works a little differently from a plain many-to-many relationship. Members have to be added to the list via instances of the association object, which in turn point to the associated object: + + {python} + user = User() + user.user_name = 'some user' + + article = Article() + + assoc = KeywordAssociation() + assoc.keyword = Keyword('blue') + assoc.user = user + + assoc2 = KeywordAssociation() + assoc2.keyword = Keyword('green') + assoc2.user = user + + article.keywords.append(assoc) + article.keywords.append(assoc2) + + session.flush() + + </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1543 => 1544)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-29 02:12:53 UTC (rev 1543) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-29 02:33:03 UTC (rev 1544) </span><span class="lines">@@ -22,6 +22,7 @@ </span><span class="cx"> self.__tcount += 1 </span><span class="cx"> def reset(self): </span><span class="cx"> try: </span><ins>+ self.__transaction.close() </ins><span class="cx"> del self.__transaction </span><span class="cx"> del self.__trans </span><span class="cx"> except AttributeError: </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 02:13:03
|
<!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>[1543] sqlalchemy/trunk/lib/sqlalchemy/databases/sqlite.py: exceptions...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1543</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 21:12:53 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>exceptions...</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemydatabasessqlitepy">sqlalchemy/trunk/lib/sqlalchemy/databases/sqlite.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemydatabasessqlitepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/databases/sqlite.py (1542 => 1543)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/databases/sqlite.py 2006-05-29 02:11:14 UTC (rev 1542) +++ sqlalchemy/trunk/lib/sqlalchemy/databases/sqlite.py 2006-05-29 02:12:53 UTC (rev 1543) </span><span class="lines">@@ -148,12 +148,9 @@ </span><span class="cx"> </span><span class="cx"> def dbapi(self): </span><span class="cx"> if sqlite is None: </span><del>- raise ArgumentError("Couldn't import sqlite or pysqlite2") </del><ins>+ raise exceptions.ArgumentError("Couldn't import sqlite or pysqlite2") </ins><span class="cx"> return sqlite </span><span class="cx"> </span><del>- def push_session(self): - raise InvalidRequestError("SQLite doesn't support nested sessions") - </del><span class="cx"> def has_table(self, connection, table_name): </span><span class="cx"> cursor = connection.execute("PRAGMA table_info(" + table_name + ")", {}) </span><span class="cx"> row = cursor.fetchone() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-29 02:11:30
|
<!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>[1542] sqlalchemy/trunk/test/pool.py: unit test adjustments to insure weakref status on connecitonfairy</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1542</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 21:11:14 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>unit test adjustments to insure weakref status on connecitonfairy</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunktestpoolpy">sqlalchemy/trunk/test/pool.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestpoolpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/pool.py (1541 => 1542)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/pool.py 2006-05-28 23:57:14 UTC (rev 1541) +++ sqlalchemy/trunk/test/pool.py 2006-05-29 02:11:14 UTC (rev 1542) </span><span class="lines">@@ -126,7 +126,9 @@ </span><span class="cx"> c2.close() </span><span class="cx"> else: </span><span class="cx"> c2 = None </span><del>- </del><ins>+ + c3 = None + </ins><span class="cx"> if useclose: </span><span class="cx"> c1 = p.connect() </span><span class="cx"> c2 = p.connect() </span><span class="lines">@@ -134,7 +136,23 @@ </span><span class="cx"> c3.close() </span><span class="cx"> c2.close() </span><span class="cx"> self.assert_(c1.connection is not None) </span><del>- </del><ins>+ c1.close() + else: + c1 = c2 = c3 = None + + # extra tests with QueuePool to insure connections get __del__()ed when dereferenced + if isinstance(p, pool.QueuePool): + self.assert_(p.checkedout() == 0) + c1 = p.connect() + c2 = p.connect() + if useclose: + c2.close() + c1.close() + else: + c2 = None + c1 = None + self.assert_(p.checkedout() == 0) + </ins><span class="cx"> def tearDown(self): </span><span class="cx"> pool.clear_managers() </span><span class="cx"> for file in ('foo.db', 'bar.db'): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 23:57:30
|
<!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>[1541] sqlalchemy/trunk/test: pool needed weakref</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1541</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 18:57:14 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>pool needed weakref modified auto rollback to only occur when no transaction more unit tests</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginebasepy">sqlalchemy/trunk/lib/sqlalchemy/engine/base.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginethreadlocalpy">sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemypoolpy">sqlalchemy/trunk/lib/sqlalchemy/pool.py</a></li> <li><a href="#sqlalchemytrunktesttransactionpy">sqlalchemy/trunk/test/transaction.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginebasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/base.py (1540 => 1541)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 20:27:08 UTC (rev 1540) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 23:57:14 UTC (rev 1541) </span><span class="lines">@@ -167,7 +167,7 @@ </span><span class="cx"> def _not_impl(self): </span><span class="cx"> raise NotImplementedError() </span><span class="cx"> engine = property(_not_impl, doc="returns the Engine which this Connectable is associated with.") </span><del>- </del><ins>+ </ins><span class="cx"> class Connection(Connectable): </span><span class="cx"> """represents a single DBAPI connection returned from the underlying connection pool. Provides </span><span class="cx"> execution support for string-based SQL statements as well as ClauseElement, Compiled and DefaultGenerator objects. </span><span class="lines">@@ -214,6 +214,9 @@ </span><span class="cx"> # extra step </span><span class="cx"> if not self.in_transaction() and re.match(r'UPDATE|INSERT|CREATE|DELETE|DROP', statement.lstrip().upper()): </span><span class="cx"> self._commit_impl() </span><ins>+ def _autorollback(self): + if not self.in_transaction(): + self._rollback_impl() </ins><span class="cx"> def close(self): </span><span class="cx"> if self.__connection is not None: </span><span class="cx"> self.__connection.close() </span><span class="lines">@@ -315,7 +318,8 @@ </span><span class="cx"> try: </span><span class="cx"> self.__engine.dialect.do_execute(c, statement, parameters, context=context) </span><span class="cx"> except Exception, e: </span><del>- self._rollback_impl() </del><ins>+ self._autorollback() + #self._rollback_impl() </ins><span class="cx"> if self.__close_with_result: </span><span class="cx"> self.close() </span><span class="cx"> raise exceptions.SQLError(statement, parameters, e) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1540 => 1541)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 20:27:08 UTC (rev 1540) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 23:57:14 UTC (rev 1541) </span><span class="lines">@@ -67,10 +67,8 @@ </span><span class="cx"> </span><span class="cx"> class TLTransaction(base.Transaction): </span><span class="cx"> def commit(self): </span><del>- print "TL COMMIT" </del><span class="cx"> base.Transaction.commit(self) </span><span class="cx"> if not self.is_active: </span><del>- print "RESET" </del><span class="cx"> self.connection.session.reset() </span><span class="cx"> def rollback(self): </span><span class="cx"> base.Transaction.rollback(self) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemypoolpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/pool.py (1540 => 1541)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/pool.py 2006-05-28 20:27:08 UTC (rev 1540) +++ sqlalchemy/trunk/lib/sqlalchemy/pool.py 2006-05-28 23:57:14 UTC (rev 1541) </span><span class="lines">@@ -71,7 +71,7 @@ </span><span class="cx"> </span><span class="cx"> class Pool(object): </span><span class="cx"> def __init__(self, echo = False, use_threadlocal = True, logger=None, **kwargs): </span><del>- self._threadconns = {} #weakref.WeakValueDictionary() </del><ins>+ self._threadconns = weakref.WeakValueDictionary() </ins><span class="cx"> self._use_threadlocal = use_threadlocal </span><span class="cx"> self.echo = echo </span><span class="cx"> self._logger = logger or util.Logger(origin='pool') </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1540 => 1541)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 20:27:08 UTC (rev 1540) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 23:57:14 UTC (rev 1541) </span><span class="lines">@@ -144,25 +144,56 @@ </span><span class="cx"> finally: </span><span class="cx"> external_connection.close() </span><span class="cx"> </span><del>- def testexplicitnesting(self): - """tests nesting of tranacstions""" </del><ins>+ def testmixednesting(self): + """tests nesting of transactions off the TLEngine directly inside of + tranasctions off the connection from the TLEngine""" </ins><span class="cx"> external_connection = tlengine.connect() </span><span class="cx"> self.assert_(external_connection.connection is not tlengine.contextual_connect().connection) </span><span class="cx"> conn = tlengine.contextual_connect() </span><span class="cx"> trans = conn.begin() </span><ins>+ trans2 = conn.begin() </ins><span class="cx"> tlengine.execute(users.insert(), user_id=1, user_name='user1') </span><span class="cx"> tlengine.execute(users.insert(), user_id=2, user_name='user2') </span><span class="cx"> tlengine.execute(users.insert(), user_id=3, user_name='user3') </span><span class="cx"> tlengine.begin() </span><span class="cx"> tlengine.execute(users.insert(), user_id=4, user_name='user4') </span><ins>+ tlengine.begin() </ins><span class="cx"> tlengine.execute(users.insert(), user_id=5, user_name='user5') </span><ins>+ tlengine.execute(users.insert(), user_id=6, user_name='user6') + tlengine.execute(users.insert(), user_id=7, user_name='user7') </ins><span class="cx"> tlengine.commit() </span><ins>+ tlengine.execute(users.insert(), user_id=8, user_name='user8') + tlengine.commit() + trans2.commit() </ins><span class="cx"> trans.rollback() </span><span class="cx"> conn.close() </span><span class="cx"> try: </span><span class="cx"> self.assert_(external_connection.scalar("select count(1) from query_users") == 0) </span><span class="cx"> finally: </span><span class="cx"> external_connection.close() </span><ins>+ + def testmoremixednesting(self): + """tests nesting of transactions off the connection from the TLEngine + inside of tranasctions off thbe TLEngine directly.""" + external_connection = tlengine.connect() + self.assert_(external_connection.connection is not tlengine.contextual_connect().connection) + tlengine.begin() + connection = tlengine.contextual_connect() + connection.execute(users.insert(), user_id=1, user_name='user1') + tlengine.begin() + connection.execute(users.insert(), user_id=2, user_name='user2') + connection.execute(users.insert(), user_id=3, user_name='user3') + trans = connection.begin() + connection.execute(users.insert(), user_id=4, user_name='user4') + connection.execute(users.insert(), user_id=5, user_name='user5') + trans.commit() + tlengine.commit() + tlengine.rollback() + connection.close() + try: + self.assert_(external_connection.scalar("select count(1) from query_users") == 0) + finally: + external_connection.close() </ins><span class="cx"> </span><span class="cx"> def testconnections(self): </span><span class="cx"> """tests that contextual_connect is threadlocal""" </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 20:27:20
|
<!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>[1540] sqlalchemy/trunk/test: more tlocal trans stuff</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1540</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 15:27:08 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>more tlocal trans stuff</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginebasepy">sqlalchemy/trunk/lib/sqlalchemy/engine/base.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginethreadlocalpy">sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py</a></li> <li><a href="#sqlalchemytrunktesttransactionpy">sqlalchemy/trunk/test/transaction.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginebasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/base.py (1539 => 1540)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 19:16:43 UTC (rev 1539) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 20:27:08 UTC (rev 1540) </span><span class="lines">@@ -345,6 +345,7 @@ </span><span class="cx"> if self.__parent is self: </span><span class="cx"> self.__connection._begin_impl() </span><span class="cx"> connection = property(lambda s:s.__connection, doc="The Connection object referenced by this Transaction") </span><ins>+ is_active = property(lambda s:s.__is_active) </ins><span class="cx"> def rollback(self): </span><span class="cx"> if not self.__parent.__is_active: </span><span class="cx"> raise exceptions.InvalidRequestError("This transaction is inactive") </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1539 => 1540)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 19:16:43 UTC (rev 1539) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 20:27:08 UTC (rev 1540) </span><span class="lines">@@ -20,27 +20,32 @@ </span><span class="cx"> self.__transaction = tlconnection </span><span class="cx"> self.__trans = trans </span><span class="cx"> self.__tcount += 1 </span><ins>+ def reset(self): + try: + del self.__transaction + del self.__trans + except AttributeError: + pass + self.__tcount = 0 + </ins><span class="cx"> def begin(self): </span><span class="cx"> if self.__tcount == 0: </span><span class="cx"> self.__transaction = self.get_connection() </span><del>- self.__trans = self.__transaction.begin() </del><ins>+ self.__trans = self.__transaction._begin() </ins><span class="cx"> self.__tcount += 1 </span><ins>+ return self.__trans </ins><span class="cx"> def rollback(self): </span><span class="cx"> if self.__tcount > 0: </span><span class="cx"> try: </span><span class="cx"> self.__trans.rollback() </span><span class="cx"> finally: </span><del>- del self.__transaction - del self.__trans - self.__tcount = 0 </del><ins>+ self.reset() </ins><span class="cx"> def commit(self): </span><span class="cx"> if self.__tcount == 1: </span><span class="cx"> try: </span><span class="cx"> self.__trans.commit() </span><span class="cx"> finally: </span><del>- del self.__transaction - del self.__trans - self.__tcount = 0 </del><ins>+ self.reset() </ins><span class="cx"> elif self.__tcount > 1: </span><span class="cx"> self.__tcount -= 1 </span><span class="cx"> def is_begun(self): </span><span class="lines">@@ -50,8 +55,28 @@ </span><span class="cx"> def __init__(self, session, close_with_result): </span><span class="cx"> base.Connection.__init__(self, session.engine, close_with_result=close_with_result) </span><span class="cx"> self.__session = session </span><del>- # TODO: get begin() to communicate with the Session to maintain the same transactional state - </del><ins>+ session = property(lambda s:s.__session) + def _create_transaction(self, parent): + return TLTransaction(self, parent) + def _begin(self): + return base.Connection.begin(self) + def begin(self): + trans = base.Connection.begin(self) + self.__session.set_transaction(self, trans) + return trans + +class TLTransaction(base.Transaction): + def commit(self): + print "TL COMMIT" + base.Transaction.commit(self) + if not self.is_active: + print "RESET" + self.connection.session.reset() + def rollback(self): + base.Transaction.rollback(self) + if not self.is_active: + self.connection.session.reset() + </ins><span class="cx"> class TLEngine(base.ComposedSQLEngine): </span><span class="cx"> """a ComposedSQLEngine that includes support for thread-local managed transactions. This engine </span><span class="cx"> is better suited to be used with threadlocal Pool object.""" </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1539 => 1540)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 19:16:43 UTC (rev 1539) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 20:27:08 UTC (rev 1540) </span><span class="lines">@@ -143,6 +143,26 @@ </span><span class="cx"> self.assert_(external_connection.scalar("select count(1) from query_users") == 0) </span><span class="cx"> finally: </span><span class="cx"> external_connection.close() </span><ins>+ + def testexplicitnesting(self): + """tests nesting of tranacstions""" + external_connection = tlengine.connect() + self.assert_(external_connection.connection is not tlengine.contextual_connect().connection) + conn = tlengine.contextual_connect() + trans = conn.begin() + tlengine.execute(users.insert(), user_id=1, user_name='user1') + tlengine.execute(users.insert(), user_id=2, user_name='user2') + tlengine.execute(users.insert(), user_id=3, user_name='user3') + tlengine.begin() + tlengine.execute(users.insert(), user_id=4, user_name='user4') + tlengine.execute(users.insert(), user_id=5, user_name='user5') + tlengine.commit() + trans.rollback() + conn.close() + try: + self.assert_(external_connection.scalar("select count(1) from query_users") == 0) + finally: + external_connection.close() </ins><span class="cx"> </span><span class="cx"> def testconnections(self): </span><span class="cx"> """tests that contextual_connect is threadlocal""" </span></span></pre> </div> </div> </body> </html> |