sqlalchemy-commits Mailing List for SQLAlchemy (Page 357)
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
|
From: <co...@sq...> - 2006-05-28 19:16:52
|
<!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>[1539] sqlalchemy/trunk/test: skips blank arguments</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1539</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 14:16:43 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>skips blank arguments</pre> <h3>Modified Paths</h3> <ul> <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="sqlalchemytrunklibsqlalchemyengineurlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/url.py (1538 => 1539)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-28 19:02:09 UTC (rev 1538) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-28 19:16:43 UTC (rev 1539) </span><span class="lines">@@ -37,7 +37,7 @@ </span><span class="cx"> sname = attribute_names.pop(0) </span><span class="cx"> if n is None: </span><span class="cx"> continue </span><del>- if getattr(self, sname, None) is not None: </del><ins>+ if getattr(self, sname, None): </ins><span class="cx"> a[n] = getattr(self, sname) </span><span class="cx"> return a </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunktestparseconnectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/parseconnect.py (1538 => 1539)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/parseconnect.py 2006-05-28 19:02:09 UTC (rev 1538) +++ sqlalchemy/trunk/test/parseconnect.py 2006-05-28 19:16:43 UTC (rev 1539) </span><span class="lines">@@ -22,7 +22,7 @@ </span><span class="cx"> ): </span><span class="cx"> u = url.make_url(text) </span><span class="cx"> print u, text </span><del>- print u.username, u.password, u.database </del><ins>+ print "username=", u.username, "password=", u.password, "database=", u.database, "host=", u.host </ins><span class="cx"> assert str(u) == text </span><span class="cx"> </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 19:02: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>[1538] sqlalchemy/trunk/test: extra tests...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1538</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 14:02:09 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>extra tests...</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginethreadlocalpy">sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py</a></li> <li><a href="#sqlalchemytrunktestparseconnectpy">sqlalchemy/trunk/test/parseconnect.py</a></li> <li><a href="#sqlalchemytrunktesttestbasepy">sqlalchemy/trunk/test/testbase.py</a></li> <li><a href="#sqlalchemytrunktesttransactionpy">sqlalchemy/trunk/test/transaction.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1537 => 1538)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 18:01:22 UTC (rev 1537) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 19:02:09 UTC (rev 1538) </span><span class="lines">@@ -14,7 +14,12 @@ </span><span class="cx"> try: </span><span class="cx"> return self.__transaction </span><span class="cx"> except AttributeError: </span><del>- return base.Connection(self.engine, close_with_result=close_with_result) </del><ins>+ return TLConnection(self, close_with_result=close_with_result) + def set_transaction(self, tlconnection, trans): + if self.__tcount == 0: + self.__transaction = tlconnection + self.__trans = trans + self.__tcount += 1 </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><span class="lines">@@ -41,7 +46,12 @@ </span><span class="cx"> def is_begun(self): </span><span class="cx"> return self.__tcount > 0 </span><span class="cx"> </span><del>- </del><ins>+class TLConnection(base.Connection): + def __init__(self, session, close_with_result): + base.Connection.__init__(self, session.engine, close_with_result=close_with_result) + self.__session = session + # TODO: get begin() to communicate with the Session to maintain the same transactional state + </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="sqlalchemytrunktestparseconnectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/parseconnect.py (1537 => 1538)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/parseconnect.py 2006-05-28 18:01:22 UTC (rev 1537) +++ sqlalchemy/trunk/test/parseconnect.py 2006-05-28 19:02:09 UTC (rev 1538) </span><span class="lines">@@ -17,10 +17,12 @@ </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><del>- 'dbtype://' </del><ins>+ 'dbtype://', + 'dbtype://username:password@/db' </ins><span class="cx"> ): </span><span class="cx"> u = url.make_url(text) </span><span class="cx"> print u, text </span><ins>+ print u.username, u.password, u.database </ins><span class="cx"> assert str(u) == text </span><span class="cx"> </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunktesttestbasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/testbase.py (1537 => 1538)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/testbase.py 2006-05-28 18:01:22 UTC (rev 1537) +++ sqlalchemy/trunk/test/testbase.py 2006-05-28 19:02:09 UTC (rev 1538) </span><span class="lines">@@ -157,8 +157,6 @@ </span><span class="cx"> raise "Invalid" </span><span class="cx"> </span><span class="cx"> def do_get(self): </span><del>- if getattr(self, 'breakpoint', False): - raise "breakpoint" </del><span class="cx"> assert self.connection is not None </span><span class="cx"> c = self.connection </span><span class="cx"> self.connection = None </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1537 => 1538)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 18:01:22 UTC (rev 1537) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 19:02:09 UTC (rev 1538) </span><span class="lines">@@ -143,6 +143,13 @@ </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 testconnections(self): + """tests that contextual_connect is threadlocal""" + c1 = tlengine.contextual_connect() + c2 = tlengine.contextual_connect() + assert c1.connection is c2.connection + c1.close() </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-28 18:01:37
|
<!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>[1537] sqlalchemy/trunk/test: do-nothing dispose() method in SingletonThreadPool</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1537</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 13:01:22 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>do-nothing dispose() method in SingletonThreadPool</pre> <h3>Modified Paths</h3> <ul> <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="sqlalchemytrunklibsqlalchemypoolpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/pool.py (1536 => 1537)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/pool.py 2006-05-28 17:59:06 UTC (rev 1536) +++ sqlalchemy/trunk/lib/sqlalchemy/pool.py 2006-05-28 18:01:22 UTC (rev 1537) </span><span class="lines">@@ -179,6 +179,8 @@ </span><span class="cx"> self._conns = {} </span><span class="cx"> self._creator = creator </span><span class="cx"> </span><ins>+ def dispose(self): + pass </ins><span class="cx"> def status(self): </span><span class="cx"> return "SingletonThreadPool id:%d thread:%d size: %d" % (id(self), thread.get_ident(), len(self._conns)) </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1536 => 1537)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 17:59:06 UTC (rev 1536) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 18:01:22 UTC (rev 1537) </span><span class="lines">@@ -127,7 +127,7 @@ </span><span class="cx"> </span><span class="cx"> @testbase.unsupported('mysql', 'sqlite') </span><span class="cx"> def testnesting(self): </span><del>- """test a basic rollback""" </del><ins>+ """tests nesting of tranacstions""" </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"> tlengine.begin() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 17:59:17
|
<!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>[1536] sqlalchemy/trunk/test: would help if commit() worked too...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1536</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 12:59:06 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>would help if commit() worked too...</pre> <h3>Modified Paths</h3> <ul> <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="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1535 => 1536)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 17:46:45 UTC (rev 1535) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 17:59:06 UTC (rev 1536) </span><span class="lines">@@ -31,10 +31,10 @@ </span><span class="cx"> def commit(self): </span><span class="cx"> if self.__tcount == 1: </span><span class="cx"> try: </span><del>- self._trans.commit() </del><ins>+ self.__trans.commit() </ins><span class="cx"> finally: </span><span class="cx"> del self.__transaction </span><del>- del self._trans </del><ins>+ del self.__trans </ins><span class="cx"> self.__tcount = 0 </span><span class="cx"> elif self.__tcount > 1: </span><span class="cx"> self.__tcount -= 1 </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1535 => 1536)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 17:46:45 UTC (rev 1535) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 17:59:06 UTC (rev 1536) </span><span class="lines">@@ -102,9 +102,29 @@ </span><span class="cx"> tlengine.execute(users.insert(), user_id=3, user_name='user3') </span><span class="cx"> tlengine.rollback() </span><span class="cx"> </span><del>- result = tlengine.execute("select * from query_users") - assert len(result.fetchall()) == 0 </del><ins>+ external_connection = tlengine.connect() + result = external_connection.execute("select * from query_users") + try: + assert len(result.fetchall()) == 0 + finally: + external_connection.close() </ins><span class="cx"> </span><ins>+ @testbase.unsupported('mysql') + def testcommit(self): + """test a basic commit""" + tlengine.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.commit() + + external_connection = tlengine.connect() + result = external_connection.execute("select * from query_users") + try: + assert len(result.fetchall()) == 3 + finally: + external_connection.close() + </ins><span class="cx"> @testbase.unsupported('mysql', 'sqlite') </span><span class="cx"> def testnesting(self): </span><span class="cx"> """test a basic rollback""" </span><span class="lines">@@ -119,8 +139,10 @@ </span><span class="cx"> tlengine.execute(users.insert(), user_id=5, user_name='user5') </span><span class="cx"> tlengine.commit() </span><span class="cx"> tlengine.rollback() </span><del>- self.assert_(external_connection.scalar("select count(1) from query_users") == 0) - external_connection.close() </del><ins>+ 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"> if __name__ == "__main__": </span><span class="cx"> testbase.main() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 17:47:01
|
<!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>[1535] sqlalchemy/trunk/test: TLEngine needed a partial rewrite....</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1535</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 12:46:45 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>TLEngine needed a partial rewrite....</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginebasepy">sqlalchemy/trunk/lib/sqlalchemy/engine/base.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginestrategiespy">sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.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 (1534 => 1535)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 16:37:22 UTC (rev 1534) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-28 17:46:45 UTC (rev 1535) </span><span class="lines">@@ -194,6 +194,8 @@ </span><span class="cx"> return self.__transaction </span><span class="cx"> else: </span><span class="cx"> return self._create_transaction(self.__transaction) </span><ins>+ def in_transaction(self): + return self.__transaction is not None </ins><span class="cx"> def _begin_impl(self): </span><span class="cx"> if self.__engine.echo: </span><span class="cx"> self.__engine.log("BEGIN") </span><span class="lines">@@ -210,13 +212,13 @@ </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="cx"> # extra step </span><del>- if self.__transaction is None and re.match(r'UPDATE|INSERT|CREATE|DELETE|DROP', statement.lstrip().upper()): </del><ins>+ if not self.in_transaction() and re.match(r'UPDATE|INSERT|CREATE|DELETE|DROP', statement.lstrip().upper()): </ins><span class="cx"> self._commit_impl() </span><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="cx"> self.__connection = None </span><del>- def scalar(self, object, parameters, **kwargs): </del><ins>+ def scalar(self, object, parameters=None, **kwargs): </ins><span class="cx"> row = self.execute(object, parameters, **kwargs).fetchone() </span><span class="cx"> if row is not None: </span><span class="cx"> return row[0] </span><span class="lines">@@ -406,6 +408,10 @@ </span><span class="cx"> conn.close() </span><span class="cx"> </span><span class="cx"> def transaction(self, callable_, connection=None, *args, **kwargs): </span><ins>+ """executes the given function within a transaction boundary. this is a shortcut for + explicitly calling begin() and commit() and optionally rollback() when execptions are raised. + The given *args and **kwargs will be passed to the function, as well as the Connection used + in the transaction.""" </ins><span class="cx"> if connection is None: </span><span class="cx"> conn = self.contextual_connect() </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginestrategiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py (1534 => 1535)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-28 16:37:22 UTC (rev 1534) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-28 17:46:45 UTC (rev 1535) </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')): </del><ins>+ for key in (('echo', 'echo_pool'), ('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> <a id="sqlalchemytrunklibsqlalchemyenginethreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py (1534 => 1535)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 16:37:22 UTC (rev 1534) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/threadlocal.py 2006-05-28 17:46:45 UTC (rev 1535) </span><span class="lines">@@ -6,39 +6,42 @@ </span><span class="cx"> will return the same connection for the same thread. also provides begin/commit methods on the engine itself </span><span class="cx"> which correspond to a thread-local transaction.""" </span><span class="cx"> </span><del>-class TLTransaction(base.Transaction): - def rollback(self): </del><ins>+class TLSession(object): + def __init__(self, engine): + self.engine = engine + self.__tcount = 0 + def get_connection(self, close_with_result=False): </ins><span class="cx"> try: </span><del>- base.Transaction.rollback(self) - finally: </del><ins>+ return self.__transaction + except AttributeError: + return base.Connection(self.engine, close_with_result=close_with_result) + def begin(self): + if self.__tcount == 0: + self.__transaction = self.get_connection() + self.__trans = self.__transaction.begin() + self.__tcount += 1 + def rollback(self): + if self.__tcount > 0: </ins><span class="cx"> try: </span><del>- del self.connection.engine.context.transaction - except AttributeError: - pass </del><ins>+ self.__trans.rollback() + finally: + del self.__transaction + del self.__trans + self.__tcount = 0 </ins><span class="cx"> def commit(self): </span><del>- try: - base.Transaction.commit(self) - stack = self.connection.engine.context.transaction - stack.pop() - if len(stack) == 0: - del self.connection.engine.context.transaction - except: </del><ins>+ if self.__tcount == 1: </ins><span class="cx"> try: </span><del>- del self.connection.engine.context.transaction - except AttributeError: - pass - raise - -class TLConnection(base.Connection): - def _create_transaction(self, parent): - return TLTransaction(self, parent) - def begin(self): - t = base.Connection.begin(self) - if not hasattr(self.engine.context, 'transaction'): - self.engine.context.transaction = [] - self.engine.context.transaction.append(t) - return t - </del><ins>+ self._trans.commit() + finally: + del self.__transaction + del self._trans + self.__tcount = 0 + elif self.__tcount > 1: + self.__tcount -= 1 + def is_begun(self): + return self.__tcount > 0 + + </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 class="lines">@@ -55,29 +58,23 @@ </span><span class="cx"> """returns a Connection that is not thread-locally scoped. this is the equilvalent to calling </span><span class="cx"> "connect()" on a ComposedSQLEngine.""" </span><span class="cx"> return base.Connection(self, self.connection_provider.unique_connection()) </span><ins>+ + def _session(self): + if not hasattr(self.context, 'session'): + self.context.session = TLSession(self) + return self.context.session + session = property(_session, doc="returns the current thread's TLSession") + </ins><span class="cx"> def contextual_connect(self, **kwargs): </span><span class="cx"> """returns a TLConnection which is thread-locally scoped.""" </span><del>- return TLConnection(self, **kwargs) </del><ins>+ return self.session.get_connection(**kwargs) + </ins><span class="cx"> def begin(self): </span><del>- return self.connect().begin() </del><ins>+ return self.session.begin() </ins><span class="cx"> def commit(self): </span><del>- if hasattr(self.context, 'transaction'): - self.context.transaction[-1].commit() </del><ins>+ self.session.commit() </ins><span class="cx"> def rollback(self): </span><del>- if hasattr(self.context, 'transaction'): - self.context.transaction[-1].rollback() - def transaction(self, func, *args, **kwargs): - """executes the given function within a transaction boundary. this is a shortcut for - explicitly calling begin() and commit() and optionally rollback() when execptions are raised. - The given *args and **kwargs will be passed to the function as well, which could be handy - in constructing decorators.""" - trans = self.begin() - try: - func(*args, **kwargs) - except: - trans.rollback() - raise - trans.commit() </del><ins>+ self.session.rollback() </ins><span class="cx"> </span><span class="cx"> class TLocalConnectionProvider(default.PoolConnectionProvider): </span><span class="cx"> def unique_connection(self): </span></span></pre></div> <a id="sqlalchemytrunktesttransactionpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/transaction.py (1534 => 1535)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/transaction.py 2006-05-28 16:37:22 UTC (rev 1534) +++ sqlalchemy/trunk/test/transaction.py 2006-05-28 17:46:45 UTC (rev 1535) </span><span class="lines">@@ -5,6 +5,7 @@ </span><span class="cx"> db = testbase.db </span><span class="cx"> from sqlalchemy import * </span><span class="cx"> </span><ins>+ </ins><span class="cx"> class TransactionTest(testbase.PersistTest): </span><span class="cx"> def setUpAll(self): </span><span class="cx"> global users, metadata </span><span class="lines">@@ -34,6 +35,23 @@ </span><span class="cx"> assert len(result.fetchall()) == 0 </span><span class="cx"> connection.close() </span><span class="cx"> </span><ins>+ def testnesting(self): + connection = testbase.db.connect() + transaction = connection.begin() + connection.execute(users.insert(), user_id=1, user_name='user1') + connection.execute(users.insert(), user_id=2, user_name='user2') + connection.execute(users.insert(), user_id=3, user_name='user3') + trans2 = connection.begin() + connection.execute(users.insert(), user_id=4, user_name='user4') + connection.execute(users.insert(), user_id=5, user_name='user5') + trans2.commit() + transaction.rollback() + self.assert_(connection.scalar("select count(1) from query_users") == 0) + + result = connection.execute("select * from query_users") + assert len(result.fetchall()) == 0 + connection.close() + </ins><span class="cx"> class AutoRollbackTest(testbase.PersistTest): </span><span class="cx"> def setUpAll(self): </span><span class="cx"> global metadata </span><span class="lines">@@ -58,6 +76,51 @@ </span><span class="cx"> # comment out the rollback in pool/ConnectionFairy._close() to see ! </span><span class="cx"> users.drop(conn2) </span><span class="cx"> conn2.close() </span><ins>+ +class TLTransactionTest(testbase.PersistTest): + def setUpAll(self): + global users, metadata, tlengine + tlengine = create_engine(testbase.db_uri, strategy='threadlocal', echo=True) + metadata = MetaData() + users = Table('query_users', metadata, + Column('user_id', INT, primary_key = True), + Column('user_name', VARCHAR(20)), + ) + users.create(tlengine) + def tearDown(self): + tlengine.execute(users.delete()) + def tearDownAll(self): + users.drop(tlengine) + tlengine.dispose() </ins><span class="cx"> </span><ins>+ @testbase.unsupported('mysql') + def testrollback(self): + """test a basic rollback""" + tlengine.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.rollback() + + result = tlengine.execute("select * from query_users") + assert len(result.fetchall()) == 0 + + @testbase.unsupported('mysql', 'sqlite') + def testnesting(self): + """test a basic rollback""" + external_connection = tlengine.connect() + self.assert_(external_connection.connection is not tlengine.contextual_connect().connection) + tlengine.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() + tlengine.rollback() + self.assert_(external_connection.scalar("select count(1) from query_users") == 0) + external_connection.close() + </ins><span class="cx"> if __name__ == "__main__": </span><span class="cx"> testbase.main() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 16:37:40
|
<!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>[1534] sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py: check for not enough inserted pks to backfill the object</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1534</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 11:37:22 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>check for not enough inserted pks to backfill the object</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 (1533 => 1534)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-28 16:12:15 UTC (rev 1533) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-28 16:37:22 UTC (rev 1534) </span><span class="lines">@@ -647,7 +647,7 @@ </span><span class="cx"> if primary_key is not None: </span><span class="cx"> i = 0 </span><span class="cx"> for col in self.pks_by_table[table]: </span><del>- if self._getattrbycolumn(obj, col) is None: </del><ins>+ if self._getattrbycolumn(obj, col) is None and len(primary_key) > i: </ins><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></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 16:12:24
|
<!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>[1533] sqlalchemy/trunk/lib/sqlalchemy/engine/url.py: raises error for bad url</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1533</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 11:12:15 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>raises error for bad url</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyengineurlpy">sqlalchemy/trunk/lib/sqlalchemy/engine/url.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyengineurlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/url.py (1532 => 1533)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-28 16:07:15 UTC (rev 1532) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/url.py 2006-05-28 16:12:15 UTC (rev 1533) </span><span class="lines">@@ -1,5 +1,6 @@ </span><span class="cx"> import re </span><span class="cx"> import cgi </span><ins>+import sqlalchemy.exceptions as exceptions </ins><span class="cx"> </span><span class="cx"> class URL(object): </span><span class="cx"> def __init__(self, drivername, username=None, password=None, host=None, port=None, database=None): </span><span class="lines">@@ -68,7 +69,7 @@ </span><span class="cx"> opts = {'username':username,'password':password,'host':host,'port':port,'database':database} </span><span class="cx"> return URL(name, **opts) </span><span class="cx"> else: </span><del>- return None </del><ins>+ raise exceptions.ArgumentError("Could not parse rfc1738 URL from string '%s'" % name) </ins><span class="cx"> </span><span class="cx"> def _parse_keyvalue_args(name): </span><span class="cx"> m = re.match( r'(\w+)://(.*)', name) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 16:07:27
|
<!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>[1532] sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py: propigate "pool" argument</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1532</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 11:07:15 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>propigate "pool" argument</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginestrategiespy">sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginestrategiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py (1531 => 1532)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-28 05:52:52 UTC (rev 1531) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/strategies.py 2006-05-28 16:07:15 UTC (rev 1532) </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')): </del><ins>+ for key in (('echo', 'echo_pool'), ('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-28 05:53:09
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><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>[1531] sqlalchemy/trunk/doc/build: selectresults docs</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1531</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-28 00:52:52 -0500 (Sun, 28 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>selectresults docs</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcompile_docstringspy">sqlalchemy/trunk/doc/build/compile_docstrings.py</a></li> <li><a href="#sqlalchemytrunkdocbuildcontentpluginstxt">sqlalchemy/trunk/doc/build/content/plugins.txt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyextselectresultspy">sqlalchemy/trunk/lib/sqlalchemy/ext/selectresults.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymodsthreadlocalpy">sqlalchemy/trunk/lib/sqlalchemy/mods/threadlocal.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcompile_docstringspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/compile_docstrings.py (1530 => 1531)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/compile_docstrings.py 2006-05-28 01:01:45 UTC (rev 1530) +++ sqlalchemy/trunk/doc/build/compile_docstrings.py 2006-05-28 05:52:52 UTC (rev 1531) </span><span class="lines">@@ -15,6 +15,7 @@ </span><span class="cx"> import sqlalchemy.ext.proxy as proxy </span><span class="cx"> import sqlalchemy.ext.sessioncontext as sessioncontext </span><span class="cx"> import sqlalchemy.mods.threadlocal as threadlocal </span><ins>+import sqlalchemy.ext.selectresults as selectresults </ins><span class="cx"> </span><span class="cx"> objects = [] </span><span class="cx"> def make_doc(obj, classes=None, functions=None): </span><span class="lines">@@ -22,15 +23,16 @@ </span><span class="cx"> </span><span class="cx"> make_doc(obj=sql, classes=[sql.Engine, sql.AbstractDialect, sql.ClauseParameters, sql.Compiled, sql.ClauseElement, sql.TableClause, sql.ColumnClause]) </span><span class="cx"> make_doc(obj=schema) </span><del>-make_doc(obj=engine, classes=[engine.ComposedSQLEngine, engine.Connection, engine.Transaction, engine.Dialect, engine.ConnectionProvider, engine.ExecutionContext, engine.ResultProxy, engine.RowProxy]) </del><ins>+make_doc(obj=engine, classes=[engine.Connectable, engine.ComposedSQLEngine, engine.Connection, engine.Transaction, engine.Dialect, engine.ConnectionProvider, engine.ExecutionContext, engine.ResultProxy, engine.RowProxy]) </ins><span class="cx"> make_doc(obj=strategies) </span><span class="cx"> make_doc(obj=orm, classes=[orm.Mapper, orm.MapperExtension]) </span><span class="cx"> make_doc(obj=orm.query, classes=[orm.query.Query]) </span><span class="cx"> make_doc(obj=orm.session, classes=[orm.session.Session, orm.session.SessionTransaction]) </span><ins>+make_doc(obj=pool, classes=[pool.DBProxy, pool.Pool, pool.QueuePool, pool.SingletonThreadPool]) </ins><span class="cx"> make_doc(obj=sessioncontext) </span><span class="cx"> make_doc(obj=threadlocal) </span><ins>+make_doc(obj=selectresults) </ins><span class="cx"> make_doc(obj=exceptions) </span><del>-make_doc(obj=pool, classes=[pool.DBProxy, pool.Pool, pool.QueuePool, pool.SingletonThreadPool]) </del><span class="cx"> make_doc(obj=proxy) </span><span class="cx"> </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunkdocbuildcontentpluginstxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/plugins.txt (1530 => 1531)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/plugins.txt 2006-05-28 01:01:45 UTC (rev 1530) +++ sqlalchemy/trunk/doc/build/content/plugins.txt 2006-05-28 05:52:52 UTC (rev 1531) </span><span class="lines">@@ -292,7 +292,7 @@ </span><span class="cx"> </span><span class="cx"> **Author:** Jonas Borgström </span><span class="cx"> </span><del>-SelectResults gives generator-like behavior to the results returned from the `select` and `select_by` method of `Query`. It supports three modes of operation; per-query, per-mapper, and per-application. </del><ins>+SelectResults gives transformative behavior to the results returned from the `select` and `select_by` method of `Query`. It supports three modes of operation; per-query, per-mapper, and per-application. </ins><span class="cx"> </span><span class="cx"> {python title="SelectResults with a Query Object"} </span><span class="cx"> from sqlalchemy.ext.selectresults import SelectResults </span><span class="lines">@@ -326,3 +326,4 @@ </span><span class="cx"> mapper(MyClass, mytable) </span><span class="cx"> session.query(MyClass).select(mytable.c.column=="something").order_by([mytable.c.column])[2:7] </span><span class="cx"> </span><ins>+For a full listing of methods, see the [generated documentation](rel:docstrings_sqlalchemy.ext.selectresults). </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyextselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ext/selectresults.py (1530 => 1531)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ext/selectresults.py 2006-05-28 01:01:45 UTC (rev 1530) +++ sqlalchemy/trunk/lib/sqlalchemy/ext/selectresults.py 2006-05-28 05:52:52 UTC (rev 1531) </span><span class="lines">@@ -1,9 +1,10 @@ </span><span class="cx"> import sqlalchemy.sql as sql </span><del>- </del><span class="cx"> import sqlalchemy.orm as orm </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> class SelectResultsExt(orm.MapperExtension): </span><ins>+ """a MapperExtension that provides SelectResults functionality for the + results of query.select_by() and query.select()""" </ins><span class="cx"> def select_by(self, query, *args, **params): </span><span class="cx"> return SelectResults(query, query.join_by(*args, **params)) </span><span class="cx"> def select(self, query, arg=None, **kwargs): </span><span class="lines">@@ -13,47 +14,65 @@ </span><span class="cx"> return SelectResults(query, arg, ops=kwargs) </span><span class="cx"> </span><span class="cx"> class SelectResults(object): </span><ins>+ """Builds a query one component at a time via separate method calls, + each call transforming the previous SelectResults instance into a new SelectResults + instance with further limiting criterion added. When interpreted + in an iterator context (such as via calling list(selectresults)), executes the query.""" + </ins><span class="cx"> def __init__(self, query, clause=None, ops={}): </span><ins>+ """constructs a new SelectResults using the given Query object and optional WHERE + clause. ops is an optional dictionary of bind parameter values.""" </ins><span class="cx"> self._query = query </span><span class="cx"> self._clause = clause </span><span class="cx"> self._ops = {} </span><span class="cx"> self._ops.update(ops) </span><span class="cx"> </span><span class="cx"> def count(self): </span><ins>+ """executes the SQL count() function against the SelectResults criterion.""" </ins><span class="cx"> return self._query.count(self._clause) </span><span class="cx"> </span><span class="cx"> def min(self, col): </span><ins>+ """executes the SQL min() function against the given column""" </ins><span class="cx"> return sql.select([sql.func.min(col)], self._clause, **self._ops).scalar() </span><span class="cx"> </span><span class="cx"> def max(self, col): </span><ins>+ """executes the SQL max() function against the given column""" </ins><span class="cx"> return sql.select([sql.func.max(col)], self._clause, **self._ops).scalar() </span><span class="cx"> </span><span class="cx"> def sum(self, col): </span><ins>+ """executes the SQL sum() function against the given column""" </ins><span class="cx"> return sql.select([sql.func.sum(col)], self._clause, **self._ops).scalar() </span><span class="cx"> </span><span class="cx"> def avg(self, col): </span><ins>+ """executes the SQL avg() function against the given column""" </ins><span class="cx"> return sql.select([sql.func.avg(col)], self._clause, **self._ops).scalar() </span><span class="cx"> </span><span class="cx"> def clone(self): </span><ins>+ """creates a copy of this SelectResults.""" </ins><span class="cx"> return SelectResults(self._query, self._clause, self._ops.copy()) </span><span class="cx"> </span><span class="cx"> def filter(self, clause): </span><ins>+ """applies an additional WHERE clause against the query.""" </ins><span class="cx"> new = self.clone() </span><span class="cx"> new._clause = sql.and_(self._clause, clause) </span><span class="cx"> return new </span><span class="cx"> </span><span class="cx"> def order_by(self, order_by): </span><ins>+ """applies an ORDER BY to the query.""" </ins><span class="cx"> new = self.clone() </span><span class="cx"> new._ops['order_by'] = order_by </span><span class="cx"> return new </span><span class="cx"> </span><span class="cx"> def limit(self, limit): </span><ins>+ """applies a LIMIT to the query.""" </ins><span class="cx"> return self[:limit] </span><span class="cx"> </span><span class="cx"> def offset(self, offset): </span><ins>+ """applies an OFFSET to the query.""" </ins><span class="cx"> return self[offset:] </span><span class="cx"> </span><span class="cx"> def list(self): </span><ins>+ """returns the results represented by this SelectResults as a list. this results in an execution of the underlying query.""" </ins><span class="cx"> return list(self) </span><span class="cx"> </span><span class="cx"> def __getitem__(self, item): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymodsthreadlocalpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mods/threadlocal.py (1530 => 1531)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/threadlocal.py 2006-05-28 01:01:45 UTC (rev 1530) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/threadlocal.py 2006-05-28 05:52:52 UTC (rev 1531) </span><span class="lines">@@ -20,6 +20,8 @@ </span><span class="cx"> while this mod is installed will reference this global context when creating new mapped object instances. </span><span class="cx"> """ </span><span class="cx"> </span><ins>+__all__ = ['Objectstore', 'assign_mapper'] + </ins><span class="cx"> class Objectstore(SessionContext): </span><span class="cx"> def __getattr__(self, key): </span><span class="cx"> return getattr(self.current, key) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 01:02:09
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><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>[1530] sqlalchemy/trunk/doc/build/content/adv_datamapping.txt: it's police....</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1530</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 20:01:45 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>it's police....</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentadv_datamappingtxt">sqlalchemy/trunk/doc/build/content/adv_datamapping.txt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentadv_datamappingtxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/adv_datamapping.txt (1529 => 1530)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/adv_datamapping.txt 2006-05-28 00:31:34 UTC (rev 1529) +++ sqlalchemy/trunk/doc/build/content/adv_datamapping.txt 2006-05-28 01:01:45 UTC (rev 1530) </span><span class="lines">@@ -235,7 +235,7 @@ </span><span class="cx"> * secondary - for a many-to-many relationship, specifies the intermediary table. </span><span class="cx"> * primaryjoin - a ClauseElement that will be used as the primary join of this child object against the parent object, or in a many-to-many relationship the join of the primary object to the association table. By default, this value is computed based on the foreign key relationships of the parent and child tables (or association table). </span><span class="cx"> * secondaryjoin - a ClauseElement that will be used as the join of an association table to the child object. By default, this value is computed based on the foreign key relationships of the association and child tables. </span><del>-* foreignkey - specifies which column in this relationship is "foreign", i.e. which column refers to the parent object. This value is automatically determined in most cases based on the primary and secondary join conditions, except in the case of a self-referential mapper, where it is needed to indicate the child object's reference back to it's parent, or in the case where the join conditions do not represent any primary key columns to properly represent the direction of the relationship. </del><ins>+* foreignkey - specifies which column in this relationship is "foreign", i.e. which column refers to the parent object. This value is automatically determined in most cases based on the primary and secondary join conditions, except in the case of a self-referential mapper, where it is needed to indicate the child object's reference back to its parent, or in the case where the join conditions do not represent any primary key columns to properly represent the direction of the relationship. </ins><span class="cx"> * uselist - a boolean that indicates if this property should be loaded as a list or a scalar. In most cases, this value is determined based on the type and direction of the relationship - one to many forms a list, many to one forms a scalar, many to many is a list. If a scalar is desired where normally a list would be present, such as a bi-directional one-to-one relationship, set uselist to False. </span><span class="cx"> * private - setting `private=True` is the equivalent of setting `cascade="all, delete-orphan"`, and indicates the lifecycle of child objects should be contained within that of the parent. See the example in [datamapping_relations_cycle](rel:datamapping_relations_lifecycle). </span><span class="cx"> * backref - indicates the name of a property to be placed on the related mapper's class that will handle this relationship in the other direction, including synchronizing the object attributes on both sides of the relation. Can also point to a `backref()` construct for more configurability. See [datamapping_relations_backreferences](rel:datamapping_relations_backreferences). </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-28 00:31:56
|
<!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>[1529] sqlalchemy/trunk/doc/build/content/sqlconstruction.txt: formatting etc</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1529</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 19:31:34 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>formatting etc</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentsqlconstructiontxt">sqlalchemy/trunk/doc/build/content/sqlconstruction.txt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentsqlconstructiontxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/sqlconstruction.txt (1528 => 1529)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/sqlconstruction.txt 2006-05-27 20:34:25 UTC (rev 1528) +++ sqlalchemy/trunk/doc/build/content/sqlconstruction.txt 2006-05-28 00:31:34 UTC (rev 1529) </span><span class="lines">@@ -127,10 +127,12 @@ </span><span class="cx"> # or get the underlying DBAPI cursor object </span><span class="cx"> cursor = result.cursor </span><span class="cx"> </span><del>- # close the result. If the statement was implicitly executed (i.e. without an explicit Connection), this will - # return the underlying connection resources back to the connection pool. de-referencing the result - # will also have the same effect. - # if an explicit Connection was used, then close() does nothing. </del><ins>+ # close the result. If the statement was implicitly executed + # (i.e. without an explicit Connection), this will + # return the underlying connection resources back to + # the connection pool. de-referencing the result + # will also have the same effect. if an explicit Connection was + # used, then close() does nothing. </ins><span class="cx"> result.close() </span><span class="cx"> </span><span class="cx"> #### Using Column Labels {@name=labels} </span><span class="lines">@@ -178,7 +180,8 @@ </span><span class="cx"> You can also specify custom labels on a per-column basis using the `label()` function: </span><span class="cx"> </span><span class="cx"> {python title="label() Function on Column"} </span><del>- {sql}c = select([users.c.user_id.label('id'), users.c.user_name.label('name')]).execute() </del><ins>+ {sql}c = select([users.c.user_id.label('id'), + users.c.user_name.label('name')]).execute() </ins><span class="cx"> SELECT users.user_id AS id, users.user_name AS name </span><span class="cx"> FROM users </span><span class="cx"> {} </span><span class="lines">@@ -319,7 +322,8 @@ </span><span class="cx"> users.select(users.c.user_id.in_(1,2,3)) </span><span class="cx"> </span><span class="cx"> # and_, endswith, equality operators </span><del>- users.select(and_(addresses.c.street.endswith('green street'), addresses.c.zip=='11234')) </del><ins>+ users.select(and_(addresses.c.street.endswith('green street'), + addresses.c.zip=='11234')) </ins><span class="cx"> </span><span class="cx"> # & operator subsituting for 'and_' </span><span class="cx"> users.select(addresses.c.street.endswith('green street') & (addresses.c.zip=='11234')) </span><span class="lines">@@ -471,7 +475,8 @@ </span><span class="cx"> A join can be created on its own using the `join` or `outerjoin` functions, or can be created off of an existing Table or other selectable unit via the `join` or `outerjoin` methods: </span><span class="cx"> </span><span class="cx"> {python} </span><del>- {sql}outerjoin(users, addresses, users.c.user_id==addresses.c.address_id).select().execute() </del><ins>+ {sql}outerjoin(users, addresses, + users.c.user_id==addresses.c.address_id).select().execute() </ins><span class="cx"> SELECT users.user_id, users.user_name, users.password, addresses.address_id, </span><span class="cx"> addresses.user_id, addresses.street, addresses.city, addresses.state, addresses.zip </span><span class="cx"> FROM users LEFT OUTER JOIN addresses ON users.user_id = addresses.address_id </span><span class="lines">@@ -581,7 +586,8 @@ </span><span class="cx"> Subqueries can be used in the column clause of a select statement by specifying the `scalar=True` flag: </span><span class="cx"> </span><span class="cx"> {python} </span><del>- {sql}select([table2.c.col1, table2.c.col2, select([table1.c.col1], table1.c.col2==7, scalar=True)]) </del><ins>+ {sql}select([table2.c.col1, table2.c.col2, + select([table1.c.col1], table1.c.col2==7, scalar=True)]) </ins><span class="cx"> SELECT table2.col1, table2.col2, </span><span class="cx"> (SELECT table1.col1 AS col1 FROM table1 WHERE col2=:table1_col2) </span><span class="cx"> FROM table2 </span><span class="lines">@@ -909,13 +915,13 @@ </span><span class="cx"> </span><span class="cx"> {python}s = select([addresses.c.city], addresses.c.user_id==users.c.user_id) </span><span class="cx"> {sql}users.update( </span><del>- and_(users.c.user_id>10, users.c.user_id&lt;20), </del><ins>+ and_(users.c.user_id>10, users.c.user_id<20), </ins><span class="cx"> values={users.c.user_name:s} </span><span class="cx"> ).execute() </span><span class="cx"> UPDATE users SET user_name=(SELECT addresses.city </span><span class="cx"> FROM addresses </span><span class="cx"> WHERE addresses.user_id = users.user_id) </span><del>- WHERE users.user_id > :users_user_id AND users.user_id &lt; :users_user_id_1 </del><ins>+ WHERE users.user_id > :users_user_id AND users.user_id < :users_user_id_1 </ins><span class="cx"> {'users_user_id_1': 20, 'users_user_id': 10} </span><span class="cx"> </span><span class="cx"> ### Deletes {@name=delete} </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 20:34:37
|
<!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>[1528] sqlalchemy/tags/rel_0_2_0/: 0.2.0</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1528</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 15:34:25 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.2.0</pre> <h3>Added Paths</h3> <ul> <li>sqlalchemy/tags/rel_0_2_0/</li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytagsrel_0_2_0fromrev1527sqlalchemytrunk"></a> <div class="copfile"><h4>Copied: sqlalchemy/tags/rel_0_2_0 (from rev 1527, sqlalchemy/trunk) ( => )</h4> <pre class="diff"><span> <span class="info"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 20:33:49
|
<!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>[1527] sqlalchemy/trunk/CHANGES: take two</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1527</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 15:33:41 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>take two</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1526 => 1527)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-05-27 20:33:22 UTC (rev 1526) +++ sqlalchemy/trunk/CHANGES 2006-05-27 20:33:41 UTC (rev 1527) </span><span class="lines">@@ -1,4 +1,4 @@ </span><del>-0.2 </del><ins>+0.2.0 </ins><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 class="cx"> including a Dialect, ConnectionProvider, etc. This impacted all the </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 20:33:37
|
<!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>[1526] sqlalchemy/trunk: 0.2 prep</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1526</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 15:33:22 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.2 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 (1525 => 1526)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-05-27 20:04:46 UTC (rev 1525) +++ sqlalchemy/trunk/CHANGES 2006-05-27 20:33:22 UTC (rev 1526) </span><span class="lines">@@ -49,6 +49,9 @@ </span><span class="cx"> - tutorial page added to docs which also can be run with a custom doctest </span><span class="cx"> runner to insure its properly working. docs generally overhauled to </span><span class="cx"> deal with new code patterns </span><ins>+- many more fixes, refactorings. +- migration guide is available on the Wiki at +http://www.sqlalchemy.org/trac/wiki/02Migration </ins><span class="cx"> </span><span class="cx"> 0.1.7 </span><span class="cx"> - some fixes to topological sort algorithm </span></span></pre></div> <a id="sqlalchemytrunksetuppy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/setup.py (1525 => 1526)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/setup.py 2006-05-27 20:04:46 UTC (rev 1525) +++ sqlalchemy/trunk/setup.py 2006-05-27 20:33:22 UTC (rev 1526) </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.0alpha", </del><ins>+ version = "0.2.0", </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-27 19:48:47
|
<!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>[1524] sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py: keep verbose false</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1524</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 14:48:34 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>keep verbose false</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormuowdumperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyormuowdumperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py (1523 => 1524)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 19:44:05 UTC (rev 1523) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 19:48:34 UTC (rev 1524) </span><span class="lines">@@ -2,7 +2,7 @@ </span><span class="cx"> """dumps out a string representation of a UOWTask structure""" </span><span class="cx"> </span><span class="cx"> class UOWDumper(object): </span><del>- def __init__(self, task, buf, verbose=True): </del><ins>+ def __init__(self, task, buf, verbose=False): </ins><span class="cx"> self.verbose = verbose </span><span class="cx"> self.indent = 0 </span><span class="cx"> self.task = task </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 19:44: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>[1523] sqlalchemy/trunk/test: latest overhaul to association objects, plus an actual unit test</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1523</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 14:44:05 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>latest overhaul to association objects, plus an actual unit test this change probably fixes [ticket:134]</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormdependencypy">sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormmapperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormuowdumperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py</a></li> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> <li><a href="#sqlalchemytrunktestrelationshipspy">sqlalchemy/trunk/test/relationships.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunktestassociationpy">sqlalchemy/trunk/test/association.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 (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/dependency.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -9,7 +9,7 @@ </span><span class="cx"> together to allow processing of scalar- and list-based dependencies at flush time.""" </span><span class="cx"> </span><span class="cx"> from sync import ONETOMANY,MANYTOONE,MANYTOMANY </span><del>-from sqlalchemy import sql </del><ins>+from sqlalchemy import sql, util </ins><span class="cx"> </span><span class="cx"> def create_dependency_processor(key, syncrules, cascade, secondary=None, association=None, is_backref=False, post_update=False): </span><span class="cx"> types = { </span><span class="lines">@@ -309,41 +309,53 @@ </span><span class="cx"> uowcommit.register_processor(stub, self, self.parent) </span><span class="cx"> def process_dependencies(self, task, deplist, uowcommit, delete = False): </span><span class="cx"> #print self.mapper.table.name + " " + self.key + " " + repr(len(deplist)) + " process_dep isdelete " + repr(delete) + " direction " + repr(self.direction) </span><del>- # manage association objects. </del><span class="cx"> for obj in deplist: </span><span class="cx"> childlist = self.get_object_dependencies(obj, uowcommit, passive=True) </span><span class="cx"> if childlist is None: continue </span><span class="cx"> </span><del>- #print "DIRECTION", self.direction - d = {} - for child in childlist: - self._synchronize(obj, child, None, False) - key = self.mapper.instance_key(child) - #print "SYNCHRONIZED", child, "INSTANCE KEY", key - d[key] = child - uowcommit.unregister_object(child) </del><ins>+ # for the association mapper, the list of association objects is organized into a unique list based on the + # "primary key". newly added association items which correspond to existing association items are "merged" + # into the existing one by moving the "_instance_key" over to the added item, so instead of insert/delete you + # just get an update operation. + if not delete: + tosave = util.OrderedDict() + for child in childlist: + self._synchronize(obj, child, None, False) + key = self.mapper.instance_key(child) + tosave[key] = child + uowcommit.unregister_object(child) </ins><span class="cx"> </span><del>- for child in childlist.added_items(): - uowcommit.register_object(child) - key = self.mapper.instance_key(child) - #print "ADDED, INSTANCE KEY", key - d[key] = child - - for child in childlist.unchanged_items(): - key = self.mapper.instance_key(child) - o = d[key] - o._instance_key= key - - for child in childlist.deleted_items(): - key = self.mapper.instance_key(child) - #print "DELETED, INSTANCE KEY", key - if d.has_key(key): - o = d[key] - o._instance_key = key </del><ins>+ todelete = {} + for child in childlist.deleted_items(): + self._synchronize(obj, child, None, False) + key = self.mapper.instance_key(child) + if not tosave.has_key(key): + todelete[key] = child + else: + tosave[key]._instance_key = key </ins><span class="cx"> uowcommit.unregister_object(child) </span><del>- else: - #print "DELETE ASSOC OBJ", repr(child) - uowcommit.register_object(child, isdelete=True) </del><ins>+ + for child in childlist.unchanged_items(): + key = self.mapper.instance_key(child) + tosave[key]._instance_key = key + + #print "OK for the save", [(o, getattr(o, '_instance_key', None)) for o in tosave.values()] + #print "OK for the delete", [(o, getattr(o, '_instance_key', None)) for o in todelete.values()] + + for obj in tosave.values(): + uowcommit.register_object(obj) + for obj in todelete.values(): + uowcommit.register_object(obj, isdelete=True) + else: + todelete = {} + for child in childlist.unchanged_items() + childlist.deleted_items(): + self._synchronize(obj, child, None, False) + key = self.mapper.instance_key(child) + todelete[key] = child + for obj in todelete.values(): + uowcommit.register_object(obj, isdelete=True) + + </ins><span class="cx"> def preprocess_dependencies(self, task, deplist, uowcommit, delete = False): </span><span class="cx"> # TODO: clean up the association step in process_dependencies and move the </span><span class="cx"> # appropriate sections of it to here </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -681,6 +681,7 @@ </span><span class="cx"> """called by a UnitOfWork object to delete objects, which involves a </span><span class="cx"> DELETE statement for each table used by this mapper, for each object in the list.""" </span><span class="cx"> connection = uow.transaction.connection(self) </span><ins>+ #print "DELETE_OBJ MAPPER", self.class_.__name__, objects </ins><span class="cx"> </span><span class="cx"> for table in util.reversed(self.tables): </span><span class="cx"> if not self._has_pks(table): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -305,6 +305,7 @@ </span><span class="cx"> if mod: self._mark_modified() </span><span class="cx"> </span><span class="cx"> def unregister_object(self, obj): </span><ins>+ #print "UNREGISTER", obj </ins><span class="cx"> mapper = object_mapper(obj) </span><span class="cx"> task = self.get_task_by_mapper(mapper) </span><span class="cx"> if obj in task.objects: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormuowdumperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -2,7 +2,7 @@ </span><span class="cx"> """dumps out a string representation of a UOWTask structure""" </span><span class="cx"> </span><span class="cx"> class UOWDumper(object): </span><del>- def __init__(self, task, buf, verbose=False): </del><ins>+ def __init__(self, task, buf, verbose=True): </ins><span class="cx"> self.verbose = verbose </span><span class="cx"> self.indent = 0 </span><span class="cx"> self.task = task </span></span></pre></div> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/test/alltests.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -40,6 +40,7 @@ </span><span class="cx"> 'objectstore', </span><span class="cx"> 'cascade', </span><span class="cx"> 'relationships', </span><ins>+ 'association', </ins><span class="cx"> </span><span class="cx"> # cyclical ORM persistence </span><span class="cx"> 'cycles', </span><span class="lines">@@ -49,7 +50,7 @@ </span><span class="cx"> 'manytomany', </span><span class="cx"> 'onetoone', </span><span class="cx"> 'inheritance', </span><del>- 'polymorph', </del><ins>+ 'polymorph', </ins><span class="cx"> </span><span class="cx"> # extensions </span><span class="cx"> 'proxy_engine', </span></span></pre></div> <a id="sqlalchemytrunktestassociationpy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/test/association.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/association.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/test/association.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -0,0 +1,143 @@ </span><ins>+import testbase + +from sqlalchemy import * + + +class AssociationTest(testbase.PersistTest): + def setUpAll(self): + global items, item_keywords, keywords, metadata, Item, Keyword, KeywordAssociation + metadata = BoundMetaData(testbase.db) + items = Table('items', metadata, + Column('item_id', Integer, primary_key=True), + Column('name', String(40)), + ) + item_keywords = Table('item_keywords', metadata, + Column('item_id', Integer, ForeignKey('items.item_id')), + Column('keyword_id', Integer, ForeignKey('keywords.keyword_id')), + Column('data', String(40)) + ) + keywords = Table('keywords', metadata, + Column('keyword_id', Integer, primary_key=True), + Column('name', String(40)) + ) + metadata.create_all() + + class Item(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return "Item id=%d name=%s keywordassoc=%s" % (self.item_id, self.name, repr(self.keywords)) + class Keyword(object): + def __init__(self, name): + self.name = name + def __repr__(self): + return "Keyword id=%d name=%s" % (self.keyword_id, self.name) + class KeywordAssociation(object): + def __init__(self, keyword, data): + self.keyword = keyword + self.data = data + def __repr__(self): + return "KeywordAssociation itemid=%d keyword=%s data=%s" % (self.item_id, repr(self.keyword), self.data) + + mapper(Keyword, keywords) + mapper(KeywordAssociation, item_keywords, properties={ + 'keyword':relation(Keyword, lazy=False) + }, primary_key=[item_keywords.c.item_id, item_keywords.c.keyword_id], order_by=[item_keywords.c.data]) + mapper(Item, items, properties={ + 'keywords' : relation(KeywordAssociation, association=Keyword) + }) + + def tearDown(self): + for t in metadata.table_iterator(reverse=True): + t.delete().execute() + def tearDownAll(self): + clear_mappers() + metadata.drop_all() + + def testinsert(self): + sess = create_session() + item1 = Item('item1') + item2 = Item('item2') + item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc')) + item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc')) + item2.keywords.append(KeywordAssociation(Keyword('green'), 'green_assoc')) + sess.save(item1) + sess.save(item2) + sess.flush() + saved = repr([item1, item2]) + sess.clear() + l = sess.query(Item).select() + loaded = repr(l) + print saved + print loaded + self.assert_(saved == loaded) + + def testreplace(self): + sess = create_session() + item1 = Item('item1') + item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc')) + item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc')) + sess.save(item1) + sess.flush() + + red_keyword = item1.keywords[1].keyword + del item1.keywords[1] + item1.keywords.append(KeywordAssociation(red_keyword, 'new_red_assoc')) + sess.flush() + saved = repr([item1]) + sess.clear() + l = sess.query(Item).select() + loaded = repr(l) + print saved + print loaded + self.assert_(saved == loaded) + + def testmodify(self): + sess = create_session() + item1 = Item('item1') + item2 = Item('item2') + item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc')) + item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc')) + item2.keywords.append(KeywordAssociation(Keyword('green'), 'green_assoc')) + sess.save(item1) + sess.save(item2) + sess.flush() + + red_keyword = item1.keywords[1].keyword + del item1.keywords[0] + del item1.keywords[0] + purple_keyword = Keyword('purple') + item1.keywords.append(KeywordAssociation(red_keyword, 'new_red_assoc')) + item2.keywords.append(KeywordAssociation(purple_keyword, 'purple_item2_assoc')) + item1.keywords.append(KeywordAssociation(purple_keyword, 'purple_item1_assoc')) + item1.keywords.append(KeywordAssociation(Keyword('yellow'), 'yellow_assoc')) + + sess.flush() + saved = repr([item1, item2]) + sess.clear() + l = sess.query(Item).select() + loaded = repr(l) + print saved + print loaded + self.assert_(saved == loaded) + + def testdelete(self): + sess = create_session() + item1 = Item('item1') + item2 = Item('item2') + item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc')) + item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc')) + item2.keywords.append(KeywordAssociation(Keyword('green'), 'green_assoc')) + sess.save(item1) + sess.save(item2) + sess.flush() + self.assert_(item_keywords.count().scalar() == 3) + + sess.delete(item1) + sess.delete(item2) + sess.flush() + self.assert_(item_keywords.count().scalar() == 0) + + +if __name__ == "__main__": + testbase.main() </ins></span></pre></div> <a id="sqlalchemytrunktestrelationshipspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/relationships.py (1522 => 1523)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/relationships.py 2006-05-27 17:51:30 UTC (rev 1522) +++ sqlalchemy/trunk/test/relationships.py 2006-05-27 19:44:05 UTC (rev 1523) </span><span class="lines">@@ -1,5 +1,3 @@ </span><del>-"""Test complex relationships""" - </del><span class="cx"> import testbase </span><span class="cx"> import unittest, sys, datetime </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 17:51: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>[1522] sqlalchemy/trunk/doc/build/content/unitofwork.txt: doc update</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1522</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 12:51:30 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>doc update</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentunitofworktxt">sqlalchemy/trunk/doc/build/content/unitofwork.txt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentunitofworktxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/unitofwork.txt (1521 => 1522)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/unitofwork.txt 2006-05-27 17:46:03 UTC (rev 1521) +++ sqlalchemy/trunk/doc/build/content/unitofwork.txt 2006-05-27 17:51:30 UTC (rev 1522) </span><span class="lines">@@ -444,25 +444,15 @@ </span><span class="cx"> </span><span class="cx"> {code} </span><span class="cx"> Task dump: </span><del>- UOWTask(6034768) 'User/users/6015696' </del><ins>+ + UOWTask(6034768, 'User/users/None') </ins><span class="cx"> | </span><del>- |- Save elements - |- Save: UOWTaskElement(6034800): User(6016624) (save) </del><ins>+ |- Save User(6016624) + | |-Process User(6016624).addresses </ins><span class="cx"> | </span><del>- |- Save dependencies - |- UOWDependencyProcessor(6035024) 'addresses' attribute on saved User's (UOWTask(6034768) 'User/users/6015696') - | |-UOWTaskElement(6034800): User(6016624) (save) - | - |- Delete dependencies - |- UOWDependencyProcessor(6035056) 'addresses' attribute on User's to be deleted (UOWTask(6034768) 'User/users/6015696') - | |-(no objects) - | - |- Child tasks - |- UOWTask(6034832) 'Address/email_addresses/6015344' - | | - | |- Save elements - | |- Save: UOWTaskElement(6034864): Address(6034384) (save) - | |- Save: UOWTaskElement(6034896): Address(6034256) (save) </del><ins>+ |- UOWTask(6034832, 'Address/email_addresses/None') + | |- Save Address(6034384) + | |- Save Address(6034256) </ins><span class="cx"> | |---- </span><span class="cx"> | </span><span class="cx"> |---- </span><span class="lines">@@ -471,5 +461,4 @@ </span><span class="cx"> </span><span class="cx"> Of course, one can also get a good idea of the order of operations just by logging the actual SQL statements executed. </span><span class="cx"> </span><del>-The format of the above display is definitely a work in progress and amazingly, is far simpler to read than it was in earlier releases. It will hopefully be further refined in future releases to be more intuitive (while not losing any information). </del><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 17:46: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>[1521] sqlalchemy/trunk/lib/sqlalchemy/orm: broke out dumper into a separate module</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1521</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 12:46:03 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>broke out dumper into a separate module</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyormuowdumperpy">sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.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 (1520 => 1521)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 16:59:07 UTC (rev 1520) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 17:46:03 UTC (rev 1521) </span><span class="lines">@@ -844,151 +844,11 @@ </span><span class="cx"> </span><span class="cx"> def dump(self): </span><span class="cx"> buf = StringIO.StringIO() </span><del>- self._dump(buf) </del><ins>+ import uowdumper + uowdumper.UOWDumper(self, buf) </ins><span class="cx"> return buf.getvalue() </span><span class="cx"> </span><del>- def _dump(self, buf, indent=0, circularparent=None): - # TODO: the dumper should go into a separate module/class, allow different dumper implementations - def _indent(): - return " | " * indent - - headers = {} - def header(buf, text): - """writes a given header just once""" - try: - headers[text] - except KeyError: - buf.write(_indent() + " |\n") - buf.write(text) - headers[text] = True - - def _dump_processor(proc, deletes): - if deletes: - val = proc.targettask.polymorphic_todelete_elements - else: - val = proc.targettask.polymorphic_tosave_elements - - buf.write(_indent() + " |- %s attribute on %s (UOWDependencyProcessor(%d) processing %s)\n" % ( - repr(proc.processor.key), - ("%s's to be %s" % (_repr_task_class(proc.targettask), deletes and "deleted" or "saved")), - id(proc), - _repr_task(proc.targettask)) - ) - - if len(val) == 0: - buf.write(_indent() + " | |-" + "(no objects)\n") - for v in val: - buf.write(_indent() + " | |-" + _repr_task_element(v, proc.processor.key) + "\n") </del><span class="cx"> </span><del>- def _repr_task_element(te, attribute=None): - if te.obj is None: - objid = "(placeholder)" - else: - if attribute is not None: - objid = "%s(%d).%s" % (te.obj.__class__.__name__, id(te.obj), attribute) - else: - objid = "%s(%d)" % (te.obj.__class__.__name__, id(te.obj)) - return "%s (UOWTaskElement(%d, %s))" % (objid, id(te), (te.listonly and 'listonly' or (te.isdelete and 'delete' or 'save'))) - - def _repr_task(task): - if task.mapper is not None: - if task.mapper.__class__.__name__ == 'Mapper': - name = task.mapper.class_.__name__ + "/" + task.mapper.local_table.name + "/" + str(task.mapper.entity_name) - else: - name = repr(task.mapper) - else: - name = '(none)' - return ("UOWTask(%d, %s)" % (id(task), name)) - def _repr_task_class(task): - if task.mapper is not None and task.mapper.__class__.__name__ == 'Mapper': - return task.mapper.class_.__name__ - else: - return '(none)' - - def _repr(obj): - return "%s(%d)" % (obj.__class__.__name__, id(obj)) - - def _inheritance_tag(task): - if task is not self: - return (" (inheriting task %s)" % _repr_task(task)) - else: - return "" - - def _dump_saveelements(task): - for rec in task.tosave_elements: - if rec.listonly: - continue - header(buf, _indent() + " |- Save elements"+ _inheritance_tag(task) + "\n") - buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") - for t in task.inheriting_tasks: - _dump_saveelements(t) - - def _dump_deleteelements(task): - for rec in task.todelete_elements: - if rec.listonly: - continue - header(buf, _indent() + " |- Delete elements"+ _inheritance_tag(task) + "\n") - buf.write(_indent() + " |- " + _repr_task_element(rec) + "\n") - for t in task.inheriting_tasks: - _dump_deleteelements(t) - - def _dump_dependencies(task): - for dep in task.dependencies: - header(buf, _indent() + " |- Save dependencies" + _inheritance_tag(task) + "\n") - _dump_processor(dep, False) - for t in task.inheriting_tasks: - _dump_dependencies(t) - for dep in task.dependencies: - header(buf, _indent() + " |- Delete dependencies" + _inheritance_tag(task) + "\n") - _dump_processor(dep, True) - - def _dump_childtasks(task): - for child in task.childtasks: - header(buf, _indent() + " |- Child tasks" + _inheritance_tag(task) + "\n") - child._dump(buf, indent + 1) - for t in task.inheriting_tasks: - _dump_childtasks(t) - - if self.circular is not None: - self.circular._dump(buf, indent, self) - return - - i = _indent() - if len(i): - i = i[0:-1] + "-" - if circularparent is not None: - buf.write(i + " " + _repr_task(circularparent)) - buf.write("->circular->" + _repr_task(self)) - else: - buf.write(i + " " + _repr_task(self)) - - buf.write("\n") - _dump_saveelements(self) - for dep in self.cyclical_dependencies: - header(buf, _indent() + " |- Cyclical Save dependencies\n") - _dump_processor(dep, False) - for element in self.tosave_elements: - for task in element.childtasks: - header(buf, _indent() + " |- Save subelements of UOWTaskElement(%s)\n" % id(element)) - task._dump(buf, indent + 1) - _dump_dependencies(self) - for dep in self.cyclical_dependencies: - header(buf, _indent() + " |- Cyclical Delete dependencies\n") - _dump_processor(dep, True) - _dump_childtasks(self) - for element in self.todelete_elements: - for task in element.childtasks: - header(buf, _indent() + " |- Delete subelements of UOWTaskElement(%s)\n" % id(element)) - task._dump(buf, indent + 1) - _dump_deleteelements(self) - - if self.is_empty(): - buf.write(_indent() + " |- (empty task)\n") - else: - buf.write(_indent() + " |----\n") - - buf.write(_indent() + "\n") - </del><span class="cx"> def __repr__(self): </span><span class="cx"> if self.mapper is not None: </span><span class="cx"> if self.mapper.__class__.__name__ == 'Mapper': </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormuowdumperpy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py (1520 => 1521)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 16:59:07 UTC (rev 1520) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/uowdumper.py 2006-05-27 17:46:03 UTC (rev 1521) </span><span class="lines">@@ -0,0 +1,188 @@ </span><ins>+ +"""dumps out a string representation of a UOWTask structure""" + +class UOWDumper(object): + def __init__(self, task, buf, verbose=False): + self.verbose = verbose + self.indent = 0 + self.task = task + self.buf = buf + self._dump(task) + + def _dump_processor(self, proc, deletes): + if deletes: + val = proc.targettask.polymorphic_todelete_elements + else: + val = proc.targettask.polymorphic_tosave_elements + + if self.verbose: + self.buf.write(self._indent() + " |- %s attribute on %s (UOWDependencyProcessor(%d) processing %s)\n" % ( + repr(proc.processor.key), + ("%s's to be %s" % (self._repr_task_class(proc.targettask), deletes and "deleted" or "saved")), + id(proc), + self._repr_task(proc.targettask)) + ) + elif False: + self.buf.write(self._indent() + " |- %s attribute on %s\n" % ( + repr(proc.processor.key), + ("%s's to be %s" % (self._repr_task_class(proc.targettask), deletes and "deleted" or "saved")), + ) + ) + + if len(val) == 0: + if self.verbose: + self.buf.write(self._indent() + " | |-" + "(no objects)\n") + for v in val: + self.buf.write(self._indent() + " | |-" + self._repr_task_element(v, proc.processor.key, process=True) + "\n") + + def _repr_task_element(self, te, attribute=None, process=False): + if te.obj is None: + objid = "(placeholder)" + else: + if attribute is not None: + objid = "%s(%d).%s" % (te.obj.__class__.__name__, id(te.obj), attribute) + else: + objid = "%s(%d)" % (te.obj.__class__.__name__, id(te.obj)) + if self.verbose: + return "%s (UOWTaskElement(%d, %s))" % (objid, id(te), (te.listonly and 'listonly' or (te.isdelete and 'delete' or 'save'))) + elif process: + return "Process %s" % (objid) + else: + return "%s %s" % ((te.isdelete and "Delete" or "Save"), objid) + + def _repr_task(self, task): + if task.mapper is not None: + if task.mapper.__class__.__name__ == 'Mapper': + name = task.mapper.class_.__name__ + "/" + task.mapper.local_table.name + "/" + str(task.mapper.entity_name) + else: + name = repr(task.mapper) + else: + name = '(none)' + return ("UOWTask(%d, %s)" % (id(task), name)) + + def _repr_task_class(self, task): + if task.mapper is not None and task.mapper.__class__.__name__ == 'Mapper': + return task.mapper.class_.__name__ + else: + return '(none)' + + def _repr(self, obj): + return "%s(%d)" % (obj.__class__.__name__, id(obj)) + + def _indent(self): + return " | " * self.indent + + def _dump(self, starttask, indent=None, circularparent=None): + try: + oldindent = self.indent + if indent is not None: + self.indent = indent + self._dump_impl(starttask, circularparent=circularparent) + finally: + self.indent = oldindent + + def _dump_impl(self, starttask, circularparent=None): + + headers = {} + def header(buf, text): + """writes a given header just once""" + try: + headers[text] + except KeyError: + self.buf.write(self._indent() + " |\n") + self.buf.write(text) + headers[text] = True + + def _inheritance_tag(task): + if not self.verbose: + return "" + elif task is not starttask: + return (" (inheriting task %s)" % self._repr_task(task)) + else: + return "" + + def _dump_saveelements(task): + for rec in task.tosave_elements: + if rec.listonly: + continue + if self.verbose: + header(self.buf, self._indent() + " |- Save elements"+ _inheritance_tag(task) + "\n") + self.buf.write(self._indent() + " |- " + self._repr_task_element(rec) + "\n") + for t in task.inheriting_tasks: + _dump_saveelements(t) + + def _dump_deleteelements(task): + for rec in task.todelete_elements: + if rec.listonly: + continue + if self.verbose: + header(self.buf, self._indent() + " |- Delete elements"+ _inheritance_tag(task) + "\n") + self.buf.write(self._indent() + " |- " + self._repr_task_element(rec) + "\n") + for t in task.inheriting_tasks: + _dump_deleteelements(t) + + def _dump_dependencies(task): + for dep in task.dependencies: + if self.verbose: + header(self.buf, self._indent() + " |- Save dependencies" + _inheritance_tag(task) + "\n") + self._dump_processor(dep, False) + for t in task.inheriting_tasks: + _dump_dependencies(t) + for dep in task.dependencies: + if self.verbose: + header(self.buf, self._indent() + " |- Delete dependencies" + _inheritance_tag(task) + "\n") + self._dump_processor(dep, True) + + def _dump_childtasks(task): + for child in task.childtasks: + if self.verbose: + header(self.buf, self._indent() + " |- Child tasks" + _inheritance_tag(task) + "\n") + self._dump(child, indent = self.indent + 1) + for t in task.inheriting_tasks: + _dump_childtasks(t) + + if starttask.circular is not None: + self._dump(starttask.circular, indent=self.indent, circularparent=starttask) + return + + i = self._indent() + if len(i): + i = i[0:-1] + "-" + if circularparent is not None: + self.buf.write(self._indent() + "\n") + self.buf.write(i + " " + self._repr_task(circularparent)) + self.buf.write("->circular->" + self._repr_task(starttask)) + else: + self.buf.write(self._indent() + "\n") + self.buf.write(i + " " + self._repr_task(starttask)) + + self.buf.write("\n") + _dump_saveelements(starttask) + for dep in starttask.cyclical_dependencies: + if self.verbose: + header(self.buf, self._indent() + " |- Cyclical Save dependencies\n") + self._dump_processor(dep, False) + for element in starttask.tosave_elements: + for task in element.childtasks: + if self.verbose: + header(self.buf, self._indent() + " |- Save subelements of UOWTaskElement(%s)\n" % id(element)) + self._dump(task, indent = self.indent + 1) + _dump_dependencies(starttask) + for dep in starttask.cyclical_dependencies: + if self.verbose: + header(self.buf, self._indent() + " |- Cyclical Delete dependencies\n") + self._dump_processor(dep, True) + _dump_childtasks(starttask) + for element in starttask.todelete_elements: + for task in element.childtasks: + if self.verbose: + header(self.buf, self._indent() + " |- Delete subelements of UOWTaskElement(%s)\n" % id(element)) + self._dump(task, indent = self.indent + 1) + _dump_deleteelements(starttask) + + if starttask.is_empty(): + self.buf.write(self._indent() + " |- (empty task)\n") + else: + self.buf.write(self._indent() + " |----\n") + + self.buf.write(self._indent() + "\n") </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 16:59: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>[1520] sqlalchemy/trunk/doc/build/content: doc updates, added 'save' method to assignmapper</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1520</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 11:59:07 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>doc updates, added 'save' method to assignmapper</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentpluginstxt">sqlalchemy/trunk/doc/build/content/plugins.txt</a></li> <li><a href="#sqlalchemytrunkdocbuildcontentunitofworktxt">sqlalchemy/trunk/doc/build/content/unitofwork.txt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyextassignmapperpy">sqlalchemy/trunk/lib/sqlalchemy/ext/assignmapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentpluginstxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/plugins.txt (1519 => 1520)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/plugins.txt 2006-05-27 16:39:05 UTC (rev 1519) +++ sqlalchemy/trunk/doc/build/content/plugins.txt 2006-05-27 16:59:07 UTC (rev 1520) </span><span class="lines">@@ -84,7 +84,7 @@ </span><span class="cx"> </span><span class="cx"> #### Attaching Mappers to their Class {@name=attaching} </span><span class="cx"> </span><del>-With `get_session()` handling the details of providing a `Session` in all cases, the `assign_mapper` function provides some of the functionality of `Query` and `Session` directly off the mapped instances themselves. This is a "monkeypatch" function that creates a primary mapper, attaches the mapper to the class, and also the methods `get, get_by, select, select_by, selectone, selectfirst, commit, expire, refresh, expunge` and `delete`: </del><ins>+With `get_session()` handling the details of providing a `Session` in all cases, the `assign_mapper` function provides some of the functionality of `Query` and `Session` directly off the mapped instances themselves. This is a "monkeypatch" function that creates a primary mapper, attaches the mapper to the class, and also the methods `get`, `select`, `select_by`, `selectone`, `get_by`, `join_to`, `join_via`, `flush`, `delete`, `expire`, `refresh`, `expunge`, `merge`, `update`, `save`, and `save_or_update`: </ins><span class="cx"> </span><span class="cx"> {python} </span><span class="cx"> # "assign" a mapper to the User class/users table </span><span class="lines">@@ -101,6 +101,8 @@ </span><span class="cx"> # flush the changes on a specific object </span><span class="cx"> myotheruser.flush() </span><span class="cx"> </span><ins>+A more generic version of `assign_mapper` that works with any `SessionContext` is available in the [plugins_assignmapper](rel:plugins_assignmapper) plugin. + </ins><span class="cx"> #### Engine Strategy Set to threadlocal By Default {@name=engine} </span><span class="cx"> </span><span class="cx"> The `threadlocal` mod also establishes `threadlocal` as the default *strategy* when calling the `create_engine()` function. This strategy is specified by the `strategy` keyword argument to `create_engine()` and can still be overridden to be "`plain`" or "`threadlocal`" explicitly. </span><span class="lines">@@ -181,7 +183,24 @@ </span><span class="cx"> # get the session corresponding to "scope2", bound to engine "someengine": </span><span class="cx"> session = ctx.current </span><span class="cx"> </span><ins>+### assignmapper </ins><span class="cx"> </span><ins>+**Author:** Mike Bayer + +This is a generic version of the `assign_mapper` function present in the [plugins_threadlocal](rel:plugins_threadlocal) mod. It requires an explicit [plugins_sessioncontext](rel:plugins_sessioncontext). + + {python} + import sqlalchemy + from sqlalchemy.ext.sessioncontext import SessionContext + from sqlalchemy.ext.assignmapper import assign_mapper + + # session context + ctx = SessionContext(sqlalchemy.create_session) + + # assign mapper to class MyClass using table 'sometable', getting + # Sessions from 'ctx'. + assign_mapper(ctx, MyClass, sometable) + </ins><span class="cx"> ### ActiveMapper </span><span class="cx"> </span><span class="cx"> **Author:** Jonathan LaCour </span><span class="lines">@@ -243,11 +262,11 @@ </span><span class="cx"> </span><span class="cx"> **Author:** Jonathan Ellis </span><span class="cx"> </span><del>-SqlSoup creates mapped classes on the fly from tables. It is essentially a nicer version of the "row data gateway" pattern. </del><ins>+SqlSoup creates mapped classes on the fly from tables, which are automatically reflected from the database based on name. It is essentially a nicer version of the "row data gateway" pattern. </ins><span class="cx"> </span><span class="cx"> {python} </span><span class="cx"> >>> from sqlalchemy.ext.sqlsoup import SqlSoup </span><del>- >>> soup = SqlSoup('sqlite://filename=:memory:') </del><ins>+ >>> soup = SqlSoup('sqlite:///') </ins><span class="cx"> </span><span class="cx"> >>> users = soup.users.select() </span><span class="cx"> >>> users.sort() </span></span></pre></div> <a id="sqlalchemytrunkdocbuildcontentunitofworktxt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/unitofwork.txt (1519 => 1520)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/unitofwork.txt 2006-05-27 16:39:05 UTC (rev 1519) +++ sqlalchemy/trunk/doc/build/content/unitofwork.txt 2006-05-27 16:59:07 UTC (rev 1520) </span><span class="lines">@@ -216,7 +216,7 @@ </span><span class="cx"> {python} </span><span class="cx"> # saves only user1 and address2. all other modified </span><span class="cx"> # objects remain present in the session. </span><del>- session.flush(user1, address2) </del><ins>+ session.flush([user1, address2]) </ins><span class="cx"> </span><span class="cx"> This second form of flush should be used carefully as it will not necessarily locate other dependent objects within the session, whose database representation may have foreign constraint relationships with the objects being operated upon. </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyextassignmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ext/assignmapper.py (1519 => 1520)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ext/assignmapper.py 2006-05-27 16:39:05 UTC (rev 1519) +++ sqlalchemy/trunk/lib/sqlalchemy/ext/assignmapper.py 2006-05-27 16:59:07 UTC (rev 1520) </span><span class="lines">@@ -33,5 +33,5 @@ </span><span class="cx"> class_.mapper = m </span><span class="cx"> for name in ['get', 'select', 'select_by', 'selectone', 'get_by', 'join_to', 'join_via']: </span><span class="cx"> monkeypatch_query_method(ctx, class_, name) </span><del>- for name in ['flush', 'delete', 'expire', 'refresh', 'expunge', 'merge', 'update', 'save_or_update']: </del><ins>+ for name in ['flush', 'delete', 'expire', 'refresh', 'expunge', 'merge', 'save', 'update', 'save_or_update']: </ins><span class="cx"> monkeypatch_objectstore_method(ctx, class_, name) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 16:39: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>[1519] sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py: circular dependency sort will not create new UOWTasks/UOWDependencyProcessors mid-stream</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1519</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 11:39:05 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>circular dependency sort will not create new UOWTasks/UOWDependencyProcessors mid-stream further construction on migrating UOWTask to be fully polymorphic</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 (1518 => 1519)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 05:45:21 UTC (rev 1518) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 16:39:05 UTC (rev 1519) </span><span class="lines">@@ -316,7 +316,7 @@ </span><span class="cx"> # raise "test assertion failed" </span><span class="cx"> self.__modified = True </span><span class="cx"> </span><del>- def get_task_by_mapper(self, mapper): </del><ins>+ def get_task_by_mapper(self, mapper, dontcreate=False): </ins><span class="cx"> """every individual mapper involved in the transaction has a single </span><span class="cx"> corresponding UOWTask object, which stores all the operations involved </span><span class="cx"> with that mapper as well as operations dependent on those operations. </span><span class="lines">@@ -325,6 +325,8 @@ </span><span class="cx"> try: </span><span class="cx"> return self.tasks[mapper] </span><span class="cx"> except KeyError: </span><ins>+ if dontcreate: + return None </ins><span class="cx"> task = UOWTask(self, mapper) </span><span class="cx"> task.mapper.register_dependencies(self) </span><span class="cx"> return task </span><span class="lines">@@ -675,20 +677,29 @@ </span><span class="cx"> self._execute_per_element_childtasks(trans, True) </span><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><del>- def _polymorphic_elements(self): </del><ins>+ def contains_object(self, obj, polymorphic=False): + if obj in self.objects: + return True + if polymorphic: + for task in self.inheriting_tasks: + if task.contains_object(obj, True): + return True + return False + + def get_elements(self, polymorphic=False): </ins><span class="cx"> for rec in self.objects.values(): </span><span class="cx"> yield rec </span><del>- for task in self.inheriting_tasks: - for rec in task._polymorphic_elements(): - 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><del>- polymorphic_tosave_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if not rec.isdelete]) - polymorphic_todelete_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if rec.isdelete]) - - tosave_elements = property(lambda self: [rec for rec in self.objects.values() if not rec.isdelete]) - todelete_elements = property(lambda self:[rec for rec in self.objects.values() if rec.isdelete]) - tosave_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is False]) - todelete_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is True]) </del><ins>+ polymorphic_tosave_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if not rec.isdelete]) + polymorphic_todelete_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=True) if rec.isdelete]) + tosave_elements = property(lambda self: [rec for rec in self.get_elements(polymorphic=False) if not rec.isdelete]) + todelete_elements = property(lambda self:[rec for rec in self.get_elements(polymorphic=False) if rec.isdelete]) + tosave_objects = property(lambda self:[rec.obj for rec in self.get_elements(polymorphic=False) if rec.obj is not None and not rec.listonly and rec.isdelete is False]) + todelete_objects = property(lambda self:[rec.obj for rec in self.get_elements(polymorphic=False) if rec.obj is not None and not rec.listonly and rec.isdelete is True]) </ins><span class="cx"> </span><span class="cx"> def _sort_circular_dependencies(self, trans, cycles): </span><span class="cx"> """for a single task, creates a hierarchical tree of "subtasks" which associate </span><span class="lines">@@ -700,7 +711,7 @@ </span><span class="cx"> a hierarchical tree is being represented.""" </span><span class="cx"> allobjects = [] </span><span class="cx"> for task in cycles: </span><del>- allobjects += task.objects.keys() </del><ins>+ allobjects += [e.obj for e in task.get_elements(polymorphic=True)] </ins><span class="cx"> tuples = [] </span><span class="cx"> </span><span class="cx"> cycles = sets.Set(cycles) </span><span class="lines">@@ -732,25 +743,28 @@ </span><span class="cx"> dp[depprocessor] = l </span><span class="cx"> return l </span><span class="cx"> </span><ins>+ def dependency_in_cycles(dep): + proctask = trans.get_task_by_mapper(dep.processor.mapper, True) + return dep.targettask in cycles and (proctask is not None and proctask in cycles) + </ins><span class="cx"> # organize all original UOWDependencyProcessors by their target task </span><span class="cx"> deps_by_targettask = {} </span><span class="cx"> for task in cycles: </span><span class="cx"> for dep in task.dependencies: </span><del>- if dep.targettask not in cycles or trans.get_task_by_mapper(dep.processor.mapper) not in cycles: </del><ins>+ if not dependency_in_cycles(dep): </ins><span class="cx"> extradeplist.append(dep) </span><span class="cx"> l = deps_by_targettask.setdefault(dep.targettask, []) </span><span class="cx"> l.append(dep) </span><span class="cx"> </span><span class="cx"> for task in cycles: </span><del>- for taskelement in task.objects.values(): </del><ins>+ for taskelement in task.get_elements(polymorphic=True): </ins><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><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>- cyclicaldep = dep.targettask in cycles and trans.get_task_by_mapper(dep.processor.mapper) in cycles - if not cyclicaldep: </del><ins>+ if not dependency_in_cycles(dep): </ins><span class="cx"> continue </span><span class="cx"> </span><span class="cx"> (processor, targettask) = (dep.processor, dep.targettask) </span><span class="lines">@@ -758,13 +772,14 @@ </span><span class="cx"> </span><span class="cx"> # list of dependent objects from this object </span><span class="cx"> childlist = dep.get_object_dependencies(obj, trans, passive = True) </span><del>- # the task corresponding to the processor's objects </del><ins>+ + # the task corresponding to saving/deleting of those dependent objects </ins><span class="cx"> childtask = trans.get_task_by_mapper(processor.mapper) </span><span class="cx"> </span><span class="cx"> childlist = childlist.added_items() + childlist.unchanged_items() + childlist.deleted_items() </span><span class="cx"> </span><span class="cx"> for o in childlist: </span><del>- if o is None or o not in childtask.objects: </del><ins>+ if o is None or not childtask.contains_object(o, polymorphic=True): </ins><span class="cx"> continue </span><span class="cx"> whosdep = dep.whose_dependent_on_who(obj, o) </span><span class="cx"> if whosdep is not None: </span><span class="lines">@@ -802,7 +817,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><del>- if original_task.objects.has_key(node.item): </del><ins>+ if original_task.contains_object(node.item, polymorphic=False): </ins><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 class="cx"> else: </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 05:45: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>[1518] sqlalchemy/trunk/lib/sqlalchemy/orm: unitofwork more Set oriented now</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1518</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-27 00:45:21 -0500 (Sat, 27 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>unitofwork more Set oriented now MapperProperty now has "localparent" and "parent" attributes, which in the case of inheritance represent the mapper the property is attached to, and the original mapper it was created on. the unitofwork now keeps the dependency processors derived from those properties unique so inheritance structures dont register redundant dependency processors.</pre> <h3>Modified Paths</h3> <ul> <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="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1517 => 1518)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-27 01:19:56 UTC (rev 1517) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-27 05:45:21 UTC (rev 1518) </span><span class="lines">@@ -932,6 +932,7 @@ </span><span class="cx"> """called when the MapperProperty is first attached to a new parent Mapper.""" </span><span class="cx"> self.key = key </span><span class="cx"> self.parent = parent </span><ins>+ self.localparent = parent </ins><span class="cx"> self.do_init(key, parent) </span><span class="cx"> def adapt(self, newparent): </span><span class="cx"> """adapts this MapperProperty to a new parent, assuming the new parent is an inheriting </span><span class="lines">@@ -939,7 +940,8 @@ </span><span class="cx"> False if this MapperProperty cannot be adapted to the new parent (the case for this is, </span><span class="cx"> the parent mapper has a polymorphic select, and this property represents a column that is not </span><span class="cx"> represented in the new mapper's mapped table)""" </span><del>- self.parent = newparent </del><ins>+ #self.parent = newparent + self.localparent = newparent </ins><span class="cx"> return True </span><span class="cx"> def do_init(self, key, parent): </span><span class="cx"> """template method for subclasses""" </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py (1517 => 1518)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-27 01:19:56 UTC (rev 1517) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-27 05:45:21 UTC (rev 1518) </span><span class="lines">@@ -38,8 +38,6 @@ </span><span class="cx"> else: </span><span class="cx"> statement.append_column(c) </span><span class="cx"> def do_init(self, key, parent): </span><del>- self.key = key - self.parent = parent </del><span class="cx"> # establish a SmartProperty property manager on the object for this key </span><span class="cx"> if parent._is_primary_mapper(): </span><span class="cx"> #print "regiser col on class %s key %s" % (parent.class_.__name__, key) </span><span class="lines">@@ -60,14 +58,12 @@ </span><span class="cx"> def copy(self): </span><span class="cx"> return DeferredColumnProperty(*self.columns) </span><span class="cx"> def do_init(self, key, parent): </span><del>- self.key = key - self.parent = parent </del><span class="cx"> # establish a SmartProperty property manager on the object for this key, </span><span class="cx"> # containing a callable to load in the attribute </span><span class="cx"> if self.is_primary(): </span><span class="cx"> sessionlib.global_attributes.register_attribute(parent.class_, key, uselist=False, callable_=lambda i:self.setup_loader(i)) </span><span class="cx"> def setup_loader(self, instance): </span><del>- if not self.parent.is_assigned(instance): </del><ins>+ if not self.localparent.is_assigned(instance): </ins><span class="cx"> return mapper.object_mapper(instance).props[self.key].setup_loader(instance) </span><span class="cx"> def lazyload(): </span><span class="cx"> session = sessionlib.object_session(instance) </span><span class="lines">@@ -85,7 +81,7 @@ </span><span class="cx"> </span><span class="cx"> try: </span><span class="cx"> if self.group is not None: </span><del>- groupcols = [p for p in self.parent.props.values() if isinstance(p, DeferredColumnProperty) and p.group==self.group] </del><ins>+ groupcols = [p for p in self.localparent.props.values() if isinstance(p, DeferredColumnProperty) and p.group==self.group] </ins><span class="cx"> row = connection.execute(sql.select([g.columns[0] for g in groupcols], clause, use_labels=True), None).fetchone() </span><span class="cx"> for prop in groupcols: </span><span class="cx"> if prop is self: </span><span class="lines">@@ -193,8 +189,6 @@ </span><span class="cx"> self.association = mapper.class_mapper(self.association) </span><span class="cx"> </span><span class="cx"> self.target = self.mapper.mapped_table </span><del>- self.key = key - self.parent = parent </del><span class="cx"> </span><span class="cx"> if self.secondaryjoin is not None and self.secondary is None: </span><span class="cx"> raise exceptions.ArgumentError("Property '" + self.key + "' specified with secondary join condition but no secondary argument") </span><span class="lines">@@ -253,7 +247,6 @@ </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>- #print self.key, repr(self.parent.mapped_table.name), repr(self.parent.primarytable.name), repr(self.foreignkey.table.name), repr(self.target), repr(self.foreigntable.name) </del><span class="cx"> </span><span class="cx"> if self.secondaryjoin is not None: </span><span class="cx"> return sync.MANYTOMANY </span><span class="lines">@@ -323,7 +316,6 @@ </span><span class="cx"> </span><span class="cx"> self.syncrules = sync.ClauseSynchronizer(self.parent, self.mapper, self.direction) </span><span class="cx"> if self.direction == sync.MANYTOMANY: </span><del>- #print "COMPILING p/c", self.parent, self.mapper </del><span class="cx"> self.syncrules.compile(self.primaryjoin, parent_tables, [self.secondary], False) </span><span class="cx"> self.syncrules.compile(self.secondaryjoin, target_tables, [self.secondary], True) </span><span class="cx"> else: </span><span class="lines">@@ -342,7 +334,7 @@ </span><span class="cx"> sessionlib.global_attributes.register_attribute(class_, key, uselist = self.uselist, callable_=lambda i: self.setup_loader(i), extension=self.attributeext, cascade=self.cascade, trackparent=True) </span><span class="cx"> </span><span class="cx"> def setup_loader(self, instance): </span><del>- if not self.parent.is_assigned(instance): </del><ins>+ if not self.localparent.is_assigned(instance): </ins><span class="cx"> return mapper.object_mapper(instance).props[self.key].setup_loader(instance) </span><span class="cx"> def lazyload(): </span><span class="cx"> params = {} </span><span class="lines">@@ -476,7 +468,7 @@ </span><span class="cx"> if isinstance(prop, EagerLoader): </span><span class="cx"> eagerprops.append(prop) </span><span class="cx"> if len(eagerprops): </span><del>- recursion_stack[self.parent.mapped_table] = True </del><ins>+ recursion_stack[self.localparent.mapped_table] = True </ins><span class="cx"> self.mapper = self.mapper.copy() </span><span class="cx"> try: </span><span class="cx"> for prop in eagerprops: </span><span class="lines">@@ -495,7 +487,7 @@ </span><span class="cx"> p.eagerprimary.accept_visitor(self.aliasizer) </span><span class="cx"> #print "new eagertqarget", p.eagertarget.name, (p.secondary and p.secondary.name or "none"), p.parent.mapped_table.name </span><span class="cx"> finally: </span><del>- del recursion_stack[self.parent.mapped_table] </del><ins>+ del recursion_stack[self.localparent.mapped_table] </ins><span class="cx"> </span><span class="cx"> self._row_decorator = self._create_decorator_row() </span><span class="cx"> </span><span class="lines">@@ -522,7 +514,7 @@ </span><span class="cx"> if hasattr(statement, '_outerjoin'): </span><span class="cx"> towrap = statement._outerjoin </span><span class="cx"> else: </span><del>- towrap = self.parent.mapped_table </del><ins>+ towrap = self.localparent.mapped_table </ins><span class="cx"> </span><span class="cx"> # print "hello, towrap", str(towrap) </span><span class="cx"> if self.secondaryjoin is not None: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1517 => 1518)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 01:19:56 UTC (rev 1517) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 05:45:21 UTC (rev 1518) </span><span class="lines">@@ -21,7 +21,7 @@ </span><span class="cx"> import StringIO </span><span class="cx"> import weakref </span><span class="cx"> import topological </span><del>-from sets import * </del><ins>+import sets </ins><span class="cx"> </span><span class="cx"> # a global indicating if all flush() operations should have their plan </span><span class="cx"> # printed to standard output. also can be affected by creating an engine </span><span class="lines">@@ -218,19 +218,19 @@ </span><span class="cx"> flush_context = UOWTransaction(self, session) </span><span class="cx"> </span><span class="cx"> if objects is not None: </span><del>- objset = util.HashSet(iter=objects) </del><ins>+ objset = sets.Set(objects) </ins><span class="cx"> else: </span><span class="cx"> objset = None </span><span class="cx"> </span><span class="cx"> for obj in [n for n in self.new] + [d for d in self.dirty]: </span><del>- if objset is not None and not objset.contains(obj): </del><ins>+ if objset is not None and not obj in objset: </ins><span class="cx"> continue </span><span class="cx"> if self.deleted.contains(obj): </span><span class="cx"> continue </span><span class="cx"> flush_context.register_object(obj) </span><span class="cx"> </span><span class="cx"> for obj in self.deleted: </span><del>- if objset is not None and not objset.contains(obj): </del><ins>+ if objset is not None and not obj in objset: </ins><span class="cx"> continue </span><span class="cx"> flush_context.register_object(obj, isdelete=True) </span><span class="cx"> </span><span class="lines">@@ -265,7 +265,7 @@ </span><span class="cx"> self.uow = uow </span><span class="cx"> self.session = session </span><span class="cx"> # unique list of all the mappers we come across </span><del>- self.mappers = util.HashSet() </del><ins>+ self.mappers = sets.Set() </ins><span class="cx"> self.dependencies = {} </span><span class="cx"> self.tasks = {} </span><span class="cx"> self.__modified = False </span><span class="lines">@@ -287,7 +287,7 @@ </span><span class="cx"> self.uow._validate_obj(obj) </span><span class="cx"> </span><span class="cx"> mapper = object_mapper(obj) </span><del>- self.mappers.append(mapper) </del><ins>+ self.mappers.add(mapper) </ins><span class="cx"> task = self.get_task_by_mapper(mapper) </span><span class="cx"> </span><span class="cx"> if postupdate: </span><span class="lines">@@ -356,7 +356,7 @@ </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="cx"> up = UOWDependencyProcessor(processor, targettask) </span><del>- task.dependencies.append(up) </del><ins>+ task.dependencies.add(up) </ins><span class="cx"> self._mark_modified() </span><span class="cx"> </span><span class="cx"> def execute(self, echo=False): </span><span class="lines">@@ -368,7 +368,7 @@ </span><span class="cx"> while True: </span><span class="cx"> ret = False </span><span class="cx"> for task in self.tasks.values(): </span><del>- for up in task.dependencies: </del><ins>+ for up in list(task.dependencies): </ins><span class="cx"> if up.preexecute(self): </span><span class="cx"> ret = True </span><span class="cx"> if not ret: </span><span class="lines">@@ -423,9 +423,9 @@ </span><span class="cx"> task.childtasks.append(t) </span><span class="cx"> return task </span><span class="cx"> </span><del>- mappers = util.HashSet() </del><ins>+ mappers = sets.Set() </ins><span class="cx"> for task in self.tasks.values(): </span><del>- mappers.append(task.mapper) </del><ins>+ mappers.add(task.mapper) </ins><span class="cx"> </span><span class="cx"> def inheriting_tasks(task): </span><span class="cx"> if task.mapper not in mappers: </span><span class="lines">@@ -436,12 +436,12 @@ </span><span class="cx"> continue </span><span class="cx"> inheriting_tasks(inherit_task) </span><span class="cx"> task.inheriting_tasks.append(inherit_task) </span><del>- del mappers[mapper] </del><ins>+ mappers.remove(mapper) </ins><span class="cx"> </span><span class="cx"> for task in self.tasks.values(): </span><span class="cx"> inheriting_tasks(task) </span><span class="cx"> </span><del>- head = DependencySorter(self.dependencies, mappers).sort(allow_all_cycles=True) </del><ins>+ head = DependencySorter(self.dependencies, list(mappers)).sort(allow_all_cycles=True) </ins><span class="cx"> #print str(head) </span><span class="cx"> task = sort_hier(head) </span><span class="cx"> return task </span><span class="lines">@@ -496,6 +496,11 @@ </span><span class="cx"> def __init__(self, processor, targettask): </span><span class="cx"> self.processor = processor </span><span class="cx"> self.targettask = targettask </span><ins>+ + def __eq__(self, other): + return other.processor is self.processor and other.targettask is self.targettask + def __hash__(self): + return hash((self.processor, self.targettask)) </ins><span class="cx"> </span><span class="cx"> def preexecute(self, trans): </span><span class="cx"> """traverses all objects handled by this dependency processor and locates additional objects which should be </span><span class="lines">@@ -537,14 +542,42 @@ </span><span class="cx"> def __init__(self, uowtransaction, mapper): </span><span class="cx"> if uowtransaction is not None: </span><span class="cx"> uowtransaction.tasks[mapper] = self </span><ins>+ + # the transaction owning this UOWTask </ins><span class="cx"> self.uowtransaction = uowtransaction </span><ins>+ + # the Mapper which this UOWTask corresponds to </ins><span class="cx"> self.mapper = mapper </span><ins>+ + # a dictionary mapping object instances to a corresponding UOWTaskElement. + # Each UOWTaskElement represents one instance which is to be saved or + # deleted by this UOWTask's Mapper. + # in the case of the row-based "circular sort", the UOWTaskElement may + # also reference further UOWTasks which are dependent on that UOWTaskElement. </ins><span class="cx"> self.objects = util.OrderedDict() </span><del>- self.dependencies = [] - self.cyclical_dependencies = [] - self.circular = None </del><ins>+ + # a list of UOWDependencyProcessors which are executed after saves and + # before deletes, to synchronize data to dependent objects + self.dependencies = sets.Set() + + # a list of UOWTasks that are dependent on this UOWTask, which + # are to be executed after this UOWTask performs saves and post-save + # dependency processing, and before pre-delete processing and deletes </ins><span class="cx"> self.childtasks = [] </span><ins>+ + # a list of UOWTasks that correspond to Mappers which are inheriting + # mappers of this UOWTask's Mapper </ins><span class="cx"> self.inheriting_tasks = [] </span><ins>+ + # whether this UOWTask is circular, meaning it holds a second + # UOWTask that contains a special row-based dependency structure + self.circular = None + + # a list of UOWDependencyProcessors are derived from the main + # set of dependencies, referencing sub-UOWTasks attached to this + # one which represent portions of the total list of objects. + # this is used for the row-based "circular sort" + self.cyclical_dependencies = sets.Set() </ins><span class="cx"> </span><span class="cx"> def is_empty(self): </span><span class="cx"> return len(self.objects) == 0 and len(self.dependencies) == 0 and len(self.childtasks) == 0 </span><span class="lines">@@ -569,8 +602,6 @@ </span><span class="cx"> rec.childtasks.append(childtask) </span><span class="cx"> if isdelete: </span><span class="cx"> rec.isdelete = True </span><del>- #if not childtask: - # rec.preprocessed = False </del><span class="cx"> return retval </span><span class="cx"> </span><span class="cx"> def append_postupdate(self, obj): </span><span class="lines">@@ -666,16 +697,13 @@ </span><span class="cx"> of its object list contain dependencies on each other. </span><span class="cx"> </span><span class="cx"> this is not the normal case; this logic only kicks in when something like </span><del>- a hierarchical tree is being represented. - - """ - </del><ins>+ a hierarchical tree is being represented.""" </ins><span class="cx"> allobjects = [] </span><span class="cx"> for task in cycles: </span><span class="cx"> allobjects += task.objects.keys() </span><span class="cx"> tuples = [] </span><span class="cx"> </span><del>- cycles = Set(cycles) </del><ins>+ cycles = sets.Set(cycles) </ins><span class="cx"> </span><span class="cx"> #print "BEGIN CIRC SORT-------" </span><span class="cx"> #print "PRE-CIRC:" </span><span class="lines">@@ -733,11 +761,6 @@ </span><span class="cx"> # the task corresponding to the processor's objects </span><span class="cx"> childtask = trans.get_task_by_mapper(processor.mapper) </span><span class="cx"> </span><del>-# if isdelete: -# childlist = childlist.unchanged_items() + childlist.deleted_items() -# else: -# childlist = childlist.added_items() - </del><span class="cx"> childlist = childlist.added_items() + childlist.unchanged_items() + childlist.deleted_items() </span><span class="cx"> </span><span class="cx"> for o in childlist: </span><span class="lines">@@ -785,14 +808,12 @@ </span><span class="cx"> else: </span><span class="cx"> t.append(node.item, original_task.objects[node.item].listonly, isdelete=original_task.objects[node.item].isdelete) </span><span class="cx"> parenttask.append(None, listonly=False, isdelete=original_task.objects[node.item].isdelete, childtask=t) </span><del>- #else: - # parenttask.append(None, listonly=False, isdelete=original_task.objects[node.item].isdelete, childtask=t) </del><span class="cx"> if dependencies.has_key(node.item): </span><span class="cx"> for depprocessor, deptask in dependencies[node.item].iteritems(): </span><span class="cx"> if can_add_to_parent: </span><del>- parenttask.cyclical_dependencies.append(depprocessor.branch(deptask)) </del><ins>+ parenttask.cyclical_dependencies.add(depprocessor.branch(deptask)) </ins><span class="cx"> else: </span><del>- t.cyclical_dependencies.append(depprocessor.branch(deptask)) </del><ins>+ t.cyclical_dependencies.add(depprocessor.branch(deptask)) </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">@@ -800,7 +821,7 @@ </span><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><del>- t.dependencies += [d for d in extradeplist] </del><ins>+ [t.dependencies.add(d) for d in extradeplist] </ins><span class="cx"> t.childtasks = self.childtasks </span><span class="cx"> make_task_tree(head, t) </span><span class="cx"> #print t.dump() </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 01:20:12
|
<!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>[1517] sqlalchemy/trunk/test: converted sqlsoup, got its doctests working (werent working in 0.1 either....), added doctest hook to testsuite</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1517</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-26 20:19:56 -0500 (Fri, 26 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>converted sqlsoup, got its doctests working (werent working in 0.1 either....), added doctest hook to testsuite fix to selectone_by/selectone when zero rows returned</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyextsqlsouppy">sqlalchemy/trunk/lib/sqlalchemy/ext/sqlsoup.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyormquerypy">sqlalchemy/trunk/lib/sqlalchemy/orm/query.py</a></li> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunktestsqlsouppy">sqlalchemy/trunk/test/sqlsoup.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyextsqlsouppy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ext/sqlsoup.py (1516 => 1517)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ext/sqlsoup.py 2006-05-27 00:16:45 UTC (rev 1516) +++ sqlalchemy/trunk/lib/sqlalchemy/ext/sqlsoup.py 2006-05-27 01:19:56 UTC (rev 1517) </span><span class="lines">@@ -1,5 +1,3 @@ </span><del>-from sqlalchemy import * - </del><span class="cx"> """ </span><span class="cx"> SqlSoup provides a convenient way to access database tables without having </span><span class="cx"> to declare table or mapper classes ahead of time. </span><span class="lines">@@ -9,16 +7,16 @@ </span><span class="cx"> For testing purposes, we can create this db as follows: </span><span class="cx"> </span><span class="cx"> >>> from sqlalchemy import create_engine </span><del>->>> e = create_engine('sqlite://filename=:memory:') ->>> for sql in _testsql: e.execute(sql) -... </del><ins>+>>> e = create_engine('sqlite:///:memory:') +>>> for sql in _testsql: e.execute(sql) #doctest: +ELLIPSIS +<... </ins><span class="cx"> </span><span class="cx"> Creating a SqlSoup gateway is just like creating an SqlAlchemy engine: </span><span class="cx"> >>> from sqlalchemy.ext.sqlsoup import SqlSoup </span><del>->>> soup = SqlSoup('sqlite://filename=:memory:') </del><ins>+>>> soup = SqlSoup('sqlite:///:memory:') </ins><span class="cx"> </span><del>-or, you can re-use an existing engine: ->>> soup = SqlSoup(e) </del><ins>+or, you can re-use an existing metadata: +>>> soup = SqlSoup(BoundMetaData(e)) </ins><span class="cx"> </span><span class="cx"> Loading objects is as easy as this: </span><span class="cx"> >>> users = soup.users.select() </span><span class="lines">@@ -28,8 +26,7 @@ </span><span class="cx"> </span><span class="cx"> Of course, letting the database do the sort is better (".c" is short for ".columns"): </span><span class="cx"> >>> soup.users.select(order_by=[soup.users.c.name]) </span><del>-[Class_Users(name='Bhargan Basepair',email='bas...@ex...',password='basepair',classname=None,admin=1), - Class_Users(name='Joe Student',email='st...@ex...',password='student',classname=None,admin=0)] </del><ins>+[Class_Users(name='Bhargan Basepair',email='bas...@ex...',password='basepair',classname=None,admin=1), Class_Users(name='Joe Student',email='st...@ex...',password='student',classname=None,admin=0)] </ins><span class="cx"> </span><span class="cx"> Field access is intuitive: </span><span class="cx"> >>> users[0].email </span><span class="lines">@@ -47,22 +44,28 @@ </span><span class="cx"> Modifying objects is intuitive: </span><span class="cx"> >>> user = _ </span><span class="cx"> >>> user.email = 'bas...@ex...' </span><del>->>> soup.commit() </del><ins>+>>> soup.flush() </ins><span class="cx"> </span><span class="cx"> (SqlSoup leverages the sophisticated SqlAlchemy unit-of-work code, so </span><span class="cx"> multiple updates to a single object will be turned into a single UPDATE </span><del>-statement when you commit.) </del><ins>+statement when you flush.) </ins><span class="cx"> </span><span class="cx"> Finally, insert and delete. Let's insert a new loan, then delete it: </span><del>->>> soup.loans.insert(book_id=soup.books.selectfirst().id, user_name=user.name) -Class_Loans(book_id=1,user_name='Bhargan Basepair',loan_date=None) ->>> soup.commit() </del><ins>+>>> soup.loans.insert(book_id=soup.books.selectfirst(soup.books.c.title=='Regional Variation in Moss').id, user_name=user.name) +Class_Loans(book_id=2,user_name='Bhargan Basepair',loan_date=None) +>>> soup.flush() </ins><span class="cx"> </span><del>->>> loan = soup.loans.selectone_by(book_id=1, user_name='Bhargan Basepair') </del><ins>+>>> loan = soup.loans.selectone_by(book_id=2, user_name='Bhargan Basepair') </ins><span class="cx"> >>> soup.delete(loan) </span><del>->>> soup.commit() </del><ins>+>>> soup.flush() </ins><span class="cx"> """ </span><span class="cx"> </span><ins>+from sqlalchemy import * +from sqlalchemy.ext.sessioncontext import SessionContext +from sqlalchemy.ext.assignmapper import assign_mapper +from sqlalchemy.exceptions import * + + </ins><span class="cx"> _testsql = """ </span><span class="cx"> CREATE TABLE books ( </span><span class="cx"> id integer PRIMARY KEY, -- auto-SERIAL in sqlite </span><span class="lines">@@ -83,7 +86,7 @@ </span><span class="cx"> book_id int PRIMARY KEY REFERENCES books(id), </span><span class="cx"> user_name varchar(32) references users(name) </span><span class="cx"> ON DELETE SET NULL ON UPDATE CASCADE, </span><del>- loan_date date NOT NULL DEFAULT current_timestamp </del><ins>+ loan_date date DEFAULT current_timestamp </ins><span class="cx"> ); </span><span class="cx"> </span><span class="cx"> insert into users(name, email, password, admin) </span><span class="lines">@@ -105,6 +108,17 @@ </span><span class="cx"> </span><span class="cx"> __all__ = ['NoSuchTableError', 'SqlSoup'] </span><span class="cx"> </span><ins>+# +# thread local SessionContext +# +class Objectstore(SessionContext): + def __getattr__(self, key): + return getattr(self.current, key) + def get_session(self): + return self.current + +objectstore = Objectstore(create_session) + </ins><span class="cx"> class NoSuchTableError(SQLAlchemyError): pass </span><span class="cx"> </span><span class="cx"> # metaclass is necessary to expose class methods with getattr, e.g. </span><span class="lines">@@ -133,7 +147,7 @@ </span><span class="cx"> L.append("%s=%r" % (k, value)) </span><span class="cx"> return '%s(%s)' % (self.__class__.__name__, ','.join(L)) </span><span class="cx"> klass.__repr__ = __repr__ </span><del>- klass._mapper = mapper(klass, table) </del><ins>+ klass._mapper = mapper(klass, table, extension=objectstore.mapper_extension) </ins><span class="cx"> return klass </span><span class="cx"> </span><span class="cx"> class SqlSoup: </span><span class="lines">@@ -142,21 +156,21 @@ </span><span class="cx"> args may either be an SQLEngine or a set of arguments suitable </span><span class="cx"> for passing to create_engine </span><span class="cx"> """ </span><del>- from sqlalchemy.engine import SQLEngine </del><ins>+ from sqlalchemy import MetaData </ins><span class="cx"> # meh, sometimes having method overloading instead of kwargs would be easier </span><del>- if isinstance(args[0], SQLEngine): </del><ins>+ if isinstance(args[0], MetaData): </ins><span class="cx"> args = list(args) </span><del>- engine = args.pop(0) </del><ins>+ metadata = args.pop(0) </ins><span class="cx"> if args or kwargs: </span><del>- raise ArgumentError('Extra arguments not allowed when engine is given') </del><ins>+ raise ArgumentError('Extra arguments not allowed when metadata is given') </ins><span class="cx"> else: </span><del>- engine = create_engine(*args, **kwargs) - self._engine = engine </del><ins>+ metadata = BoundMetaData(*args, **kwargs) + self._metadata = metadata </ins><span class="cx"> self._cache = {} </span><span class="cx"> def delete(self, *args, **kwargs): </span><span class="cx"> objectstore.delete(*args, **kwargs) </span><del>- def commit(self): - objectstore.get_session().commit() </del><ins>+ def flush(self): + objectstore.get_session().flush() </ins><span class="cx"> def rollback(self): </span><span class="cx"> objectstore.clear() </span><span class="cx"> def _reset(self): </span><span class="lines">@@ -167,7 +181,7 @@ </span><span class="cx"> try: </span><span class="cx"> t = self._cache[attr] </span><span class="cx"> except KeyError: </span><del>- table = Table(attr, self._engine, autoload=True) </del><ins>+ table = Table(attr, self._metadata, autoload=True) </ins><span class="cx"> if table.columns: </span><span class="cx"> t = class_for_table(table) </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/query.py (1516 => 1517)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/query.py 2006-05-27 00:16:45 UTC (rev 1516) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/query.py 2006-05-27 01:19:56 UTC (rev 1517) </span><span class="lines">@@ -169,7 +169,10 @@ </span><span class="cx"> ret = self.select_whereclause(self.join_by(*args, **params), limit=2) </span><span class="cx"> if len(ret) == 1: </span><span class="cx"> return ret[0] </span><del>- raise exceptions.InvalidRequestError('Multiple rows returned for selectone_by') </del><ins>+ elif len(ret) == 0: + raise exceptions.InvalidRequestError('No rows returned for selectone_by') + else: + raise exceptions.InvalidRequestError('Multiple rows returned for selectone_by') </ins><span class="cx"> </span><span class="cx"> def count_by(self, *args, **params): </span><span class="cx"> """returns the count of instances based on the given clauses and key/value criterion. </span><span class="lines">@@ -191,7 +194,10 @@ </span><span class="cx"> ret = list(self.select(*args, **params)[0:2]) </span><span class="cx"> if len(ret) == 1: </span><span class="cx"> return ret[0] </span><del>- raise exceptions.InvalidRequestError('Multiple rows returned for selectone') </del><ins>+ elif len(ret) == 0: + raise exceptions.InvalidRequestError('No rows returned for selectone_by') + else: + raise exceptions.InvalidRequestError('Multiple rows returned for selectone') </ins><span class="cx"> </span><span class="cx"> def select(self, arg=None, **kwargs): </span><span class="cx"> """selects instances of the object from the database. </span></span></pre></div> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1516 => 1517)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-05-27 00:16:45 UTC (rev 1516) +++ sqlalchemy/trunk/test/alltests.py 2006-05-27 01:19:56 UTC (rev 1517) </span><span class="lines">@@ -53,7 +53,9 @@ </span><span class="cx"> </span><span class="cx"> # extensions </span><span class="cx"> 'proxy_engine', </span><del>- 'activemapper' </del><ins>+ 'activemapper', + 'sqlsoup' + </ins><span class="cx"> #'wsgi_test', </span><span class="cx"> </span><span class="cx"> ) </span></span></pre></div> <a id="sqlalchemytrunktestsqlsouppy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/test/sqlsoup.py (1516 => 1517)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/sqlsoup.py 2006-05-27 00:16:45 UTC (rev 1516) +++ sqlalchemy/trunk/test/sqlsoup.py 2006-05-27 01:19:56 UTC (rev 1517) </span><span class="lines">@@ -0,0 +1,19 @@ </span><ins>+import testbase + +import sqlalchemy.ext.sqlsoup as sqlsoup + +class SqlSoupTest(testbase.AssertMixin): + def tearDown(self): + pass + def tearDownAll(self): + pass + def setUpAll(self): + pass + def setUp(self): + pass + def testall(self): + import doctest + doctest.testmod(m=sqlsoup,verbose=True) + +if __name__ == "__main__": + testbase.main() </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 00:16: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>[1516] sqlalchemy/trunk/lib/sqlalchemy/databases/mssql.py: merged r.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1516</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-26 19:16:45 -0500 (Fri, 26 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>merged r. morrisons 0.2 update from branch to trunk</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemydatabasesmssqlpy">sqlalchemy/trunk/lib/sqlalchemy/databases/mssql.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemydatabasesmssqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/databases/mssql.py (1515 => 1516)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/databases/mssql.py 2006-05-27 00:13:12 UTC (rev 1515) +++ sqlalchemy/trunk/lib/sqlalchemy/databases/mssql.py 2006-05-27 00:16:45 UTC (rev 1516) </span><span class="lines">@@ -38,10 +38,11 @@ </span><span class="cx"> </span><span class="cx"> import sqlalchemy.sql as sql </span><span class="cx"> import sqlalchemy.engine as engine </span><ins>+import sqlalchemy.engine.default as default </ins><span class="cx"> import sqlalchemy.schema as schema </span><span class="cx"> import sqlalchemy.ansisql as ansisql </span><span class="cx"> import sqlalchemy.types as sqltypes </span><del>-from sqlalchemy import * </del><ins>+import sqlalchemy.exceptions as exceptions </ins><span class="cx"> </span><span class="cx"> try: </span><span class="cx"> import adodbapi as dbmodule </span><span class="lines">@@ -65,10 +66,10 @@ </span><span class="cx"> make_connect_string = lambda keys: [[],{}] </span><span class="cx"> </span><span class="cx"> class MSNumeric(sqltypes.Numeric): </span><del>- def convert_result_value(self, value, engine): </del><ins>+ def convert_result_value(self, value, dialect): </ins><span class="cx"> return value </span><span class="cx"> </span><del>- def convert_bind_param(self, value, engine): </del><ins>+ def convert_bind_param(self, value, dialect): </ins><span class="cx"> if value is None: </span><span class="cx"> # Not sure that this exception is needed </span><span class="cx"> return value </span><span class="lines">@@ -81,7 +82,7 @@ </span><span class="cx"> class MSFloat(sqltypes.Float): </span><span class="cx"> def get_col_spec(self): </span><span class="cx"> return "FLOAT(%(precision)s)" % {'precision': self.precision} </span><del>- def convert_bind_param(self, value, engine): </del><ins>+ def convert_bind_param(self, value, dialect): </ins><span class="cx"> """By converting to string, we can use Decimal types round-trip.""" </span><span class="cx"> return str(value) </span><span class="cx"> </span><span class="lines">@@ -97,13 +98,14 @@ </span><span class="cx"> def get_col_spec(self): </span><span class="cx"> return "DATETIME" </span><span class="cx"> </span><del>- def convert_bind_param(self, value, engine): </del><ins>+ def convert_bind_param(self, value, dialect): </ins><span class="cx"> if hasattr(value, "isoformat"): </span><del>- return value.isoformat(' ') </del><ins>+ #return value.isoformat(' ') + return value.strftime('%Y-%m-%d %H:%M:%S') # isoformat() bings on apodbapi -- reported/suggested by Peter Buschman </ins><span class="cx"> else: </span><span class="cx"> return value </span><span class="cx"> </span><del>- def convert_result_value(self, value, engine): </del><ins>+ def convert_result_value(self, value, dialect): </ins><span class="cx"> # adodbapi will return datetimes with empty time values as datetime.date() objects. Promote them back to full datetime.datetime() </span><span class="cx"> if value and not hasattr(value, 'second'): </span><span class="cx"> return datetime.datetime(value.year, value.month, value.day) </span><span class="lines">@@ -113,12 +115,12 @@ </span><span class="cx"> def get_col_spec(self): </span><span class="cx"> return "SMALLDATETIME" </span><span class="cx"> </span><del>- def convert_bind_param(self, value, engine): </del><ins>+ def convert_bind_param(self, value, dialect): </ins><span class="cx"> if value and hasattr(value, "isoformat"): </span><span class="cx"> return value.isoformat() </span><span class="cx"> return value </span><span class="cx"> </span><del>- def convert_result_value(self, value, engine): </del><ins>+ def convert_result_value(self, value, dialect): </ins><span class="cx"> # pymssql will return SMALLDATETIME values as datetime.datetime(), truncate it back to datetime.date() </span><span class="cx"> if value and hasattr(value, 'second'): </span><span class="cx"> return value.date() </span><span class="lines">@@ -184,16 +186,49 @@ </span><span class="cx"> ('host',"Hostname", None), </span><span class="cx"> ]} </span><span class="cx"> </span><del>-class MSSQLEngine(ansisql.ANSISQLEngine): - def __init__(self, opts, module = None, **params): - if module is None: - self.module = dbmodule - self.opts = opts or {} - ansisql.ANSISQLEngine.__init__(self, **params) </del><ins>+class MSSQLExecutionContext(default.DefaultExecutionContext): + def pre_exec(self, engine, proxy, compiled, parameters, **kwargs): + """ MS-SQL has a special mode for inserting non-NULL values into IDENTITY columns. Activate it if needed. """ + if getattr(compiled, "isinsert", False): + self.IINSERT = False + self.HASIDENT = False + for c in compiled.statement.table.c: + if hasattr(c,'sequence'): + self.HASIDENT = True + if parameters.has_key(c.name): + self.IINSERT = True + break + if self.IINSERT: + proxy("SET IDENTITY_INSERT %s ON" % compiled.statement.table.name) </ins><span class="cx"> </span><ins>+ def post_exec(self, engine, proxy, compiled, parameters, **kwargs): + """ Turn off the INDENTITY_INSERT mode if it's been activated, and fetch recently inserted IDENTIFY values (works only for one column) """ + if getattr(compiled, "isinsert", False): + if self.IINSERT: + proxy("SET IDENTITY_INSERT %s OFF" % compiled.statement.table.name) + self.IINSERT = False + elif self.HASIDENT: + cursor = proxy("SELECT @@IDENTITY AS lastrowid") + row = cursor.fetchone() + self.last_inserted_ids = [row[0]] + self.HASIDENT = False + +class MSSQLDialect(ansisql.ANSIDialect): + def __init__(self, module = None, **params): + self.module = module or dbmodule + self.opts = {} + ansisql.ANSIDialect.__init__(self, **params) + + def create_connect_args(self, url): + self.opts = url.translate_connect_args(['host', 'database', 'user', 'password', 'port']) + return ([], self.opts) + </ins><span class="cx"> def connect_args(self): </span><span class="cx"> return make_connect_string(self.opts) </span><span class="cx"> </span><ins>+ def create_execution_context(self): + return MSSQLExecutionContext(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><span class="lines">@@ -204,14 +239,17 @@ </span><span class="cx"> return True </span><span class="cx"> </span><span class="cx"> def compiler(self, statement, bindparams, **kwargs): </span><del>- return MSSQLCompiler(statement, bindparams, engine=self, **kwargs) </del><ins>+ return MSSQLCompiler(self, statement, bindparams, **kwargs) </ins><span class="cx"> </span><del>- def schemagenerator(self, **params): - return MSSQLSchemaGenerator(self, **params) </del><ins>+ def schemagenerator(self, *args, **kwargs): + return MSSQLSchemaGenerator(*args, **kwargs) </ins><span class="cx"> </span><del>- def schemadropper(self, **params): - return MSSQLSchemaDropper(self, **params) </del><ins>+ def schemadropper(self, *args, **kwargs): + return MSSQLSchemaDropper(*args, **kwargs) </ins><span class="cx"> </span><ins>+ def defaultrunner(self, engine, proxy): + return MSSQLDefaultRunner(engine, proxy) + </ins><span class="cx"> def get_default_schema_name(self): </span><span class="cx"> return "dbo" </span><span class="cx"> </span><span class="lines">@@ -229,10 +267,10 @@ </span><span class="cx"> self.context.rowcount = c.rowcount </span><span class="cx"> c.DBPROP_COMMITPRESERVE = "Y" </span><span class="cx"> except Exception, e: </span><del>- # del c.parent # Close the Parent Connection, delete it from the pool </del><ins>+ # del c.parent # Close the Parent Connection, delete it from the pool columns = ischema.columns.toengine(self) + </ins><span class="cx"> raise exceptions.SQLError(statement, parameters, e) </span><span class="cx"> </span><del>- </del><span class="cx"> def do_rollback(self, connection): </span><span class="cx"> """implementations might want to put logic here for turning autocommit on/off, etc.""" </span><span class="cx"> if do_commit: </span><span class="lines">@@ -288,36 +326,11 @@ </span><span class="cx"> c.supportsTransactions = 0 </span><span class="cx"> return c </span><span class="cx"> </span><del>- def pre_exec(self, proxy, compiled, parameters, **kwargs): - """ MS-SQL has a special mode for inserting non-NULL values into IDENTITY columns. Activate it if needed. """ - if getattr(compiled, "isinsert", False): - self.context.IINSERT = False - self.context.HASIDENT = False - for c in compiled.statement.table.c: - if hasattr(c,'sequence'): - self.context.HASIDENT = True - if parameters.has_key(c.name): - self.context.IINSERT = True - break - if self.context.IINSERT: - proxy("SET IDENTITY_INSERT %s ON" % compiled.statement.table.name) - - def post_exec(self, proxy, compiled, parameters, **kwargs): - """ Turn off the INDENTITY_INSERT mode if it's been activated, and fetch recently inserted IDENTIFY values (works only for one column) """ - if getattr(compiled, "isinsert", False): - if self.context.IINSERT: - proxy("SET IDENTITY_INSERT %s OFF" % compiled.statement.table.name) - self.context.IINSERT = False - elif self.context.HASIDENT: - cursor = proxy("SELECT @@IDENTITY AS lastrowid") - row = cursor.fetchone() - self.context.last_inserted_ids = [row[0]] - self.context.HASIDENT = False - </del><ins>+ </ins><span class="cx"> def dbapi(self): </span><span class="cx"> return self.module </span><span class="cx"> </span><del>- def reflecttable(self, table): </del><ins>+ def reflecttable(self, connection, table): </ins><span class="cx"> import sqlalchemy.databases.information_schema as ischema </span><span class="cx"> </span><span class="cx"> # Get base columns </span><span class="lines">@@ -326,12 +339,12 @@ </span><span class="cx"> else: </span><span class="cx"> current_schema = self.get_default_schema_name() </span><span class="cx"> </span><del>- columns = ischema.gen_columns.toengine(self) </del><ins>+ columns = ischema.columns.toengine(self) </ins><span class="cx"> s = select([columns], </span><span class="cx"> current_schema and sql.and_(columns.c.table_name==table.name, columns.c.table_schema==current_schema) or columns.c.table_name==table.name, </span><span class="cx"> order_by=[columns.c.ordinal_position]) </span><span class="cx"> </span><del>- c = s.execute() </del><ins>+ c = connection.execute(s) </ins><span class="cx"> while True: </span><span class="cx"> row = c.fetchone() </span><span class="cx"> if row is None: </span><span class="lines">@@ -352,7 +365,6 @@ </span><span class="cx"> if a is not None: </span><span class="cx"> args.append(a) </span><span class="cx"> coltype = ischema_names[type] </span><del>- </del><span class="cx"> coltype = coltype(*args) </span><span class="cx"> colargs= [] </span><span class="cx"> if default is not None: </span><span class="lines">@@ -363,7 +375,9 @@ </span><span class="cx"> </span><span class="cx"> # We also run an sp_columns to check for identity columns: </span><span class="cx"> # FIXME: note that this only fetches the existence of an identity column, not it's properties like (seed, increment) </span><del>- cursor = table.engine.execute("sp_columns " + table.name, {}) </del><ins>+ # also, add a check to make sure we specify the schema name of the table + # cursor = table.engine.execute("sp_columns " + table.name, {}) + cursor = connection.execute("sp_columns " + table.name) </ins><span class="cx"> while True: </span><span class="cx"> row = cursor.fetchone() </span><span class="cx"> if row is None: </span><span class="lines">@@ -375,10 +389,10 @@ </span><span class="cx"> ic.sequence = schema.Sequence(ic.name + '_identity') </span><span class="cx"> </span><span class="cx"> # Add constraints </span><del>- RR = ischema.gen_ref_constraints.toengine(self) #information_schema.referential_constraints - TC = ischema.gen_constraints.toengine(self) #information_schema.table_constraints - C = ischema.gen_column_constraints.toengine(self).alias('C') #information_schema.constraint_column_usage: the constrained column - R = ischema.gen_column_constraints.toengine(self).alias('R') #information_schema.constraint_column_usage: the referenced column </del><ins>+ RR = ischema.ref_constraints.toengine(self) #information_schema.referential_constraints + TC = ischema.constraints.toengine(self) #information_schema.table_constraints + C = ischema.column_constraints.toengine(self).alias('C') #information_schema.constraint_column_usage: the constrained column + R = ischema.column_constraints.toengine(self).alias('R') #information_schema.constraint_column_usage: the referenced column </ins><span class="cx"> </span><span class="cx"> fromjoin = TC.join(RR, RR.c.constraint_name == TC.c.constraint_name).join(C, C.c.constraint_name == RR.c.constraint_name) </span><span class="cx"> fromjoin = fromjoin.join(R, R.c.constraint_name == RR.c.unique_constraint_name) </span><span class="lines">@@ -389,7 +403,7 @@ </span><span class="cx"> from_obj = [fromjoin] </span><span class="cx"> ) </span><span class="cx"> </span><del>- c = s.execute() </del><ins>+ c = connection.execute(s) </ins><span class="cx"> </span><span class="cx"> while True: </span><span class="cx"> row = c.fetchone() </span><span class="lines">@@ -412,8 +426,8 @@ </span><span class="cx"> </span><span class="cx"> </span><span class="cx"> class MSSQLCompiler(ansisql.ANSICompiler): </span><del>- def __init__(self, *args, **kwargs): - super(MSSQLCompiler, self).__init__(*args, **kwargs) </del><ins>+ def __init__(self, dialect, statement, parameters, **kwargs): + super(MSSQLCompiler, self).__init__(dialect, statement, parameters, **kwargs) </ins><span class="cx"> self.tablealiases = {} </span><span class="cx"> </span><span class="cx"> def visit_select_precolumns(self, select): </span><span class="lines">@@ -463,7 +477,7 @@ </span><span class="cx"> colspec = column.name + " " + column.type.engine_impl(self.engine).get_col_spec() </span><span class="cx"> </span><span class="cx"> # install a IDENTITY Sequence if we have an implicit IDENTITY column </span><del>- if column.primary_key and isinstance(column.type, types.Integer): </del><ins>+ if column.primary_key and isinstance(column.type, sqltypes.Integer): </ins><span class="cx"> if column.default is None or (isinstance(column.default, schema.Sequence) and column.default.optional): </span><span class="cx"> column.sequence = schema.Sequence(column.name + '_seq') </span><span class="cx"> </span><span class="lines">@@ -490,3 +504,8 @@ </span><span class="cx"> def visit_index(self, index): </span><span class="cx"> self.append("\nDROP INDEX " + index.table.name + "." + index.name) </span><span class="cx"> self.execute() </span><ins>+ +class MSSQLDefaultRunner(ansisql.ANSIDefaultRunner): + pass + +dialect = MSSQLDialect </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-27 00:13:27
|
<!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>[1515] sqlalchemy/trunk/test: added has_key to RowProxy, + caching of key lookups</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1515</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-26 19:13:12 -0500 (Fri, 26 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>added has_key to RowProxy, + caching of key lookups fix for mapper translate_row for deferred columns continuing with the "polymorph-tizing" of the unit of work, dependency processing accesses objects on each target task polymorphically</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginebasepy">sqlalchemy/trunk/lib/sqlalchemy/engine/base.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> <li><a href="#sqlalchemytrunktestinheritancepy">sqlalchemy/trunk/test/inheritance.py</a></li> <li><a href="#sqlalchemytrunktestselectpy">sqlalchemy/trunk/test/select.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 (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/lib/sqlalchemy/engine/base.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -506,6 +506,7 @@ </span><span class="cx"> self.closed = False </span><span class="cx"> self.executioncontext = executioncontext </span><span class="cx"> self.echo = engine.echo=="debug" </span><ins>+ self.__key_cache = {} </ins><span class="cx"> if executioncontext: </span><span class="cx"> self.rowcount = executioncontext.get_rowcount(cursor) </span><span class="cx"> else: </span><span class="lines">@@ -534,19 +535,36 @@ </span><span class="cx"> self.closed = True </span><span class="cx"> if self.connection.should_close_with_result and self.dialect.supports_autoclose_results: </span><span class="cx"> self.connection.close() </span><del>- def _get_col(self, row, key): - if isinstance(key, sql.ColumnElement): - try: - rec = self.props[key._label.lower()] - except KeyError: </del><ins>+ + def _convert_key(self, key): + """given a key, which could be a ColumnElement, string, etc., matches it to the + appropriate key we got from the result set's metadata; then cache it locally for quick re-access.""" + try: + return self.__key_cache[key] + except KeyError: + if isinstance(key, sql.ColumnElement): </ins><span class="cx"> try: </span><del>- rec = self.props[key.key.lower()] </del><ins>+ rec = self.props[key._label.lower()] </ins><span class="cx"> except KeyError: </span><del>- rec = self.props[key.name.lower()] - elif isinstance(key, str): - rec = self.props[key.lower()] - else: - rec = self.props[key] </del><ins>+ try: + rec = self.props[key.key.lower()] + except KeyError: + rec = self.props[key.name.lower()] + elif isinstance(key, str): + rec = self.props[key.lower()] + else: + rec = self.props[key] + self.__key_cache[key] = rec + return rec + def _has_key(self, row, key): + try: + self._convert_key(key) + return True + except KeyError: + return False + + def _get_col(self, row, key): + rec = self._convert_key(key) </ins><span class="cx"> return rec[0].dialect_impl(self.dialect).convert_result_value(row[rec[1]], self.dialect) </span><span class="cx"> </span><span class="cx"> def __iter__(self): </span><span class="lines">@@ -605,6 +623,8 @@ </span><span class="cx"> return (other is self) or (other == tuple([self.__parent._get_col(self.__row, key) for key in range(0, len(self.__row))])) </span><span class="cx"> def __repr__(self): </span><span class="cx"> return repr(tuple([self.__parent._get_col(self.__row, key) for key in range(0, len(self.__row))])) </span><ins>+ def has_key(self, key): + return self.__parent._has_key(self.__row, key) </ins><span class="cx"> def __getitem__(self, key): </span><span class="cx"> return self.__parent._get_col(self.__row, key) </span><span class="cx"> def __getattr__(self, name): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/mapper.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -822,7 +822,8 @@ </span><span class="cx"> newrow = util.DictDecorator(row) </span><span class="cx"> for c in tomapper.mapped_table.c: </span><span class="cx"> c2 = self.mapped_table.corresponding_column(c, keys_ok=True, raiseerr=True) </span><del>- newrow[c] = row[c2] </del><ins>+ if row.has_key(c2): + newrow[c] = row[c2] </ins><span class="cx"> return newrow </span><span class="cx"> </span><span class="cx"> def populate_instance(self, session, instance, row, identitykey, imap, isnew, frommapper=None): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/properties.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -581,6 +581,8 @@ </span><span class="cx"> class DecoratorDict(object): </span><span class="cx"> def __init__(self, row): </span><span class="cx"> self.row = row </span><ins>+ def has_key(self, key): + return map.has_key(key) or self.row.has_key(key) </ins><span class="cx"> def __getitem__(self, key): </span><span class="cx"> if map.has_key(key): </span><span class="cx"> key = map[key] </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyormunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/lib/sqlalchemy/orm/unitofwork.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -506,12 +506,12 @@ </span><span class="cx"> return elem.obj </span><span class="cx"> </span><span class="cx"> ret = False </span><del>- elements = [getobj(elem) for elem in self.targettask.tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)] </del><ins>+ elements = [getobj(elem) for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None and not elem.is_preprocessed(self)] </ins><span class="cx"> if len(elements): </span><span class="cx"> ret = True </span><span class="cx"> self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=False) </span><span class="cx"> </span><del>- elements = [getobj(elem) for elem in self.targettask.todelete_elements if elem.obj is not None and not elem.is_preprocessed(self)] </del><ins>+ elements = [getobj(elem) for elem in self.targettask.polymorphic_todelete_elements if elem.obj is not None and not elem.is_preprocessed(self)] </ins><span class="cx"> if len(elements): </span><span class="cx"> ret = True </span><span class="cx"> self.processor.preprocess_dependencies(self.targettask, elements, trans, delete=True) </span><span class="lines">@@ -519,9 +519,9 @@ </span><span class="cx"> </span><span class="cx"> def execute(self, trans, delete): </span><span class="cx"> if not delete: </span><del>- self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.tosave_elements if elem.obj is not None], trans, delete=False) </del><ins>+ self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.polymorphic_tosave_elements if elem.obj is not None], trans, delete=False) </ins><span class="cx"> else: </span><del>- self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.todelete_elements if elem.obj is not None], trans, delete=True) </del><ins>+ self.processor.process_dependencies(self.targettask, [elem.obj for elem in self.targettask.polymorphic_todelete_elements if elem.obj is not None], trans, delete=True) </ins><span class="cx"> </span><span class="cx"> def get_object_dependencies(self, obj, trans, passive): </span><span class="cx"> return self.processor.get_object_dependencies(obj, trans, passive=passive) </span><span class="lines">@@ -533,6 +533,7 @@ </span><span class="cx"> return UOWDependencyProcessor(self.processor, task) </span><span class="cx"> </span><span class="cx"> class UOWTask(object): </span><ins>+ """represents the full list of objects that are to be saved/deleted by a specific Mapper.""" </ins><span class="cx"> def __init__(self, uowtransaction, mapper): </span><span class="cx"> if uowtransaction is not None: </span><span class="cx"> uowtransaction.tasks[mapper] = self </span><span class="lines">@@ -603,6 +604,22 @@ </span><span class="cx"> child.execute(trans) </span><span class="cx"> for task in self.inheriting_tasks: </span><span class="cx"> task._execute_childtasks(trans) </span><ins>+ def _execute_cyclical_dependencies(self, trans, isdelete): + for dep in self.cyclical_dependencies: + dep.execute(trans, isdelete) + for task in self.inheriting_tasks: + task._execute_cyclical_dependencies(trans, isdelete) + def _execute_per_element_childtasks(self, trans, isdelete): + if isdelete: + for element in self.todelete_elements: + for task in element.childtasks: + task.execute(trans) + else: + for element in self.tosave_elements: + for task in element.childtasks: + task.execute(trans) + for task in self.inheriting_tasks: + task._execute_per_element_childtasks(trans, isdelete) </ins><span class="cx"> </span><span class="cx"> def execute(self, trans): </span><span class="cx"> """executes this UOWTask. saves objects to be saved, processes all dependencies </span><span class="lines">@@ -615,25 +632,28 @@ </span><span class="cx"> self.circular.execute(trans) </span><span class="cx"> return </span><span class="cx"> </span><del>- # TODO: apply the same recursive inheritance logic to the cyclical tasks/dependencies </del><span class="cx"> # TODO: add a visitation system to the UOW classes and have this execution called </span><span class="cx"> # from a separate executor object ? (would also handle dumping) </span><span class="cx"> </span><span class="cx"> self._save_objects(trans) </span><del>- for dep in self.cyclical_dependencies: - dep.execute(trans, False) - for element in self.tosave_elements: - for task in element.childtasks: - task.execute(trans) </del><ins>+ self._execute_cyclical_dependencies(trans, False) + self._execute_per_element_childtasks(trans, False) </ins><span class="cx"> self._execute_dependencies(trans) </span><del>- for dep in self.cyclical_dependencies: - dep.execute(trans, True) </del><ins>+ self._execute_cyclical_dependencies(trans, True) </ins><span class="cx"> self._execute_childtasks(trans) </span><del>- for element in self.todelete_elements: - for task in element.childtasks: - task.execute(trans) </del><ins>+ self._execute_per_element_childtasks(trans, True) </ins><span class="cx"> self._delete_objects(trans) </span><span class="cx"> </span><ins>+ def _polymorphic_elements(self): + for rec in self.objects.values(): + yield rec + for task in self.inheriting_tasks: + for rec in task._polymorphic_elements(): + yield rec + + polymorphic_tosave_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if not rec.isdelete]) + polymorphic_todelete_elements = property(lambda self: [rec for rec in self._polymorphic_elements() if rec.isdelete]) + </ins><span class="cx"> tosave_elements = property(lambda self: [rec for rec in self.objects.values() if not rec.isdelete]) </span><span class="cx"> todelete_elements = property(lambda self:[rec for rec in self.objects.values() if rec.isdelete]) </span><span class="cx"> tosave_objects = property(lambda self:[rec.obj for rec in self.objects.values() if rec.obj is not None and not rec.listonly and rec.isdelete is False]) </span><span class="lines">@@ -808,9 +828,9 @@ </span><span class="cx"> </span><span class="cx"> def _dump_processor(proc, deletes): </span><span class="cx"> if deletes: </span><del>- val = [t for t in proc.targettask.objects.values() if t.isdelete] </del><ins>+ val = proc.targettask.polymorphic_todelete_elements </ins><span class="cx"> else: </span><del>- val = [t for t in proc.targettask.objects.values() if not t.isdelete] </del><ins>+ val = proc.targettask.polymorphic_tosave_elements </ins><span class="cx"> </span><span class="cx"> buf.write(_indent() + " |- %s attribute on %s (UOWDependencyProcessor(%d) processing %s)\n" % ( </span><span class="cx"> repr(proc.processor.key), </span></span></pre></div> <a id="sqlalchemytrunktestinheritancepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/inheritance.py (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/inheritance.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/test/inheritance.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -350,7 +350,8 @@ </span><span class="cx"> #contents.add_property('content_type', relation(content_types)) #adding this makes the inheritance stop working </span><span class="cx"> # shouldnt throw exception </span><span class="cx"> products = mapper(Product, product, inherits=contents) </span><del>- </del><ins>+ # TODO: assertion ?? + </ins><span class="cx"> def testbackref(self): </span><span class="cx"> """tests adding a property to the superclass mapper""" </span><span class="cx"> class ContentType(object): pass </span><span class="lines">@@ -364,6 +365,7 @@ </span><span class="cx"> }) </span><span class="cx"> p = Product() </span><span class="cx"> p.contenttype = ContentType() </span><ins>+ # TODO: assertion ?? </ins><span class="cx"> </span><span class="cx"> class InheritTest6(testbase.AssertMixin): </span><span class="cx"> """tests eager load/lazy load of child items off inheritance mappers, tests that </span></span></pre></div> <a id="sqlalchemytrunktestselectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/select.py (1514 => 1515)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/select.py 2006-05-26 23:35:56 UTC (rev 1514) +++ sqlalchemy/trunk/test/select.py 2006-05-27 00:13:12 UTC (rev 1515) </span><span class="lines">@@ -3,6 +3,7 @@ </span><span class="cx"> from sqlalchemy.databases import sqlite, postgres, mysql, oracle </span><span class="cx"> from testbase import PersistTest </span><span class="cx"> import unittest, re </span><ins>+import testbase </ins><span class="cx"> </span><span class="cx"> # the select test now tests almost completely with TableClause/ColumnClause objects, </span><span class="cx"> # which are free-roaming table/column objects not attached to any database. </span><span class="lines">@@ -645,4 +646,4 @@ </span><span class="cx"> self.runtest(table4.insert(values=(2, 5, 'test')), "INSERT INTO remote_owner.remotetable (rem_id, datatype_id, value) VALUES (:rem_id, :datatype_id, :value)") </span><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span><del>- unittest.main() </del><ins>+ testbase.main() </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-05-26 23:36:07
|
<!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>[1514] sqlalchemy/trunk/test/inheritance2.py: uncompleted additional inheritance tests</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1514</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-05-26 18:35:56 -0500 (Fri, 26 May 2006)</dd> </dl> <h3>Log Message</h3> <pre>uncompleted additional inheritance tests</pre> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunktestinheritance2py">sqlalchemy/trunk/test/inheritance2.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunktestinheritance2py"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/test/inheritance2.py (1513 => 1514)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/inheritance2.py 2006-05-25 21:14:00 UTC (rev 1513) +++ sqlalchemy/trunk/test/inheritance2.py 2006-05-26 23:35:56 UTC (rev 1514) </span><span class="lines">@@ -0,0 +1,336 @@ </span><ins>+# UNDER CONSTRUCTION ! +# I am just pasting vladimir iliev's test cases here where they will be later assembled into unit tests. + +from sqlalchemy import * +from datetime import datetime + +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)), + 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.), + ) + + +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) + ) + + + +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, + 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, + ) + ) + + +metadata.create_all() +session = create_session(echo_uow=True) + + +a1 = Assembly(name='a1') + +p1 = Product(name='p1') +a1.specification.append(SpecLine(slave=p1)) + +d1 = Detail(name='d1') +a1.specification.append(SpecLine(slave=d1)) + +session.save(a1) + +session.flush() +session.clear() + +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) + ) + +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) + ) + + +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 + + +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 + + +# ============================================================================================================================== </ins><span class="cx">\ No newline at end of file </span></span></pre> </div> </div> </body> </html> |