sqlalchemy-commits Mailing List for SQLAlchemy (Page 369)
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-03-31 22:28: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>[1232] sqlalchemy/trunk/test: added for_update flag to Select/CompoundSelect</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1232</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-31 16:28:17 -0600 (Fri, 31 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>added for_update flag to Select/CompoundSelect</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyansisqlpy">sqlalchemy/trunk/lib/sqlalchemy/ansisql.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> <li><a href="#sqlalchemytrunktestselectpy">sqlalchemy/trunk/test/select.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyansisqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/ansisql.py (1231 => 1232)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2006-03-31 07:36:51 UTC (rev 1231) +++ sqlalchemy/trunk/lib/sqlalchemy/ansisql.py 2006-03-31 22:28:17 UTC (rev 1232) </span><span class="lines">@@ -373,6 +373,9 @@ </span><span class="cx"> </span><span class="cx"> text += self.visit_select_postclauses(select) </span><span class="cx"> </span><ins>+ if select.for_update: + text += " FOR UPDATE" + </ins><span class="cx"> if getattr(select, 'parens', False): </span><span class="cx"> self.strings[select] = "(" + text + ")" </span><span class="cx"> else: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1231 => 1232)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-31 07:36:51 UTC (rev 1231) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-31 22:28:17 UTC (rev 1232) </span><span class="lines">@@ -1176,6 +1176,7 @@ </span><span class="cx"> self.use_labels = kwargs.pop('use_labels', False) </span><span class="cx"> self.parens = kwargs.pop('parens', False) </span><span class="cx"> self.correlate = kwargs.pop('correlate', False) </span><ins>+ self.for_update = kwargs.pop('for_update', False) </ins><span class="cx"> self.oid_column = selects[0].oid_column </span><span class="cx"> for s in self.selects: </span><span class="cx"> s.group_by(None) </span><span class="lines">@@ -1211,7 +1212,7 @@ </span><span class="cx"> class Select(SelectBaseMixin, FromClause): </span><span class="cx"> """represents a SELECT statement, with appendable clauses, as well as </span><span class="cx"> the ability to execute itself and return a result set.""" </span><del>- def __init__(self, columns=None, whereclause = None, from_obj = [], order_by = None, group_by=None, having=None, use_labels = False, distinct=False, engine = None, limit=None, offset=None, scalar=False, correlate=True): </del><ins>+ def __init__(self, columns=None, whereclause = None, from_obj = [], order_by = None, group_by=None, having=None, use_labels = False, distinct=False, for_update=False, engine=None, limit=None, offset=None, scalar=False, correlate=True): </ins><span class="cx"> self._froms = util.OrderedDict() </span><span class="cx"> self.use_labels = use_labels </span><span class="cx"> self.name = None </span><span class="lines">@@ -1221,6 +1222,7 @@ </span><span class="cx"> self.oid_column = None </span><span class="cx"> self.limit = limit </span><span class="cx"> self.offset = offset </span><ins>+ self.for_update = for_update </ins><span class="cx"> </span><span class="cx"> # indicates that this select statement should not expand its columns </span><span class="cx"> # into the column clause of an enclosing select, and should instead </span></span></pre></div> <a id="sqlalchemytrunktestselectpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/select.py (1231 => 1232)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/select.py 2006-03-31 07:36:51 UTC (rev 1231) +++ sqlalchemy/trunk/test/select.py 2006-03-31 22:28:17 UTC (rev 1232) </span><span class="lines">@@ -240,6 +240,11 @@ </span><span class="cx"> select([table2.c.othername, func.count(table2.c.otherid)], group_by = [table2.c.othername], order_by = [table2.c.othername]), </span><span class="cx"> "SELECT myothertable.othername, count(myothertable.otherid) FROM myothertable GROUP BY myothertable.othername ORDER BY myothertable.othername" </span><span class="cx"> ) </span><ins>+ + def testforupdate(self): + self.runtest( + table1.select(table1.c.myid==7, for_update=True), "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid = :mytable_myid FOR UPDATE" + ) </ins><span class="cx"> def testalias(self): </span><span class="cx"> # test the alias for a table1. column names stay the same, table name "changes" to "foo". </span><span class="cx"> self.runtest( </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-31 07:37:03
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1231] sqlalchemy/trunk/lib/sqlalchemy/mods: adjustments...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1231</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-31 01:36:51 -0600 (Fri, 31 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>adjustments...</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymodsselectresultspy">sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1230 => 1231)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 07:29:28 UTC (rev 1230) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 07:36:51 UTC (rev 1231) </span><span class="lines">@@ -58,9 +58,10 @@ </span><span class="cx"> </span><span class="cx"> for ext_class in global_extensions: </span><span class="cx"> ext = ext_class().chain(ext) </span><del>- - for ext_obj in util.to_list(extension): - ext = ext_obj.chain(ext) </del><ins>+ + if extension is not None: + for ext_obj in util.to_list(extension): + ext = ext_obj.chain(ext) </ins><span class="cx"> </span><span class="cx"> self.extension = ext </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymodsselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py (1230 => 1231)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 07:29:28 UTC (rev 1230) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 07:36:51 UTC (rev 1231) </span><span class="lines">@@ -13,6 +13,8 @@ </span><span class="cx"> return mapping.EXT_PASS </span><span class="cx"> else: </span><span class="cx"> return SelectResults(mapper, arg, ops=kwargs) </span><ins>+ +MapperExtension = SelectResultsExt </ins><span class="cx"> </span><span class="cx"> class SelectResults(object): </span><span class="cx"> def __init__(self, mapper, clause=None, ops={}): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-31 07:29: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>[1230] sqlalchemy/trunk/lib/sqlalchemy/mods: tweak...</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1230</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-31 01:29:28 -0600 (Fri, 31 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>tweak...</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymodsselectresultspy">sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1229 => 1230)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 07:22:45 UTC (rev 1229) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 07:29:28 UTC (rev 1230) </span><span class="lines">@@ -19,8 +19,8 @@ </span><span class="cx"> # a dictionary mapping classes to their primary mappers </span><span class="cx"> mapper_registry = weakref.WeakKeyDictionary() </span><span class="cx"> </span><del>-# a list of MapperExtensions that will be installed by default -extensions = [] </del><ins>+# a list of MapperExtensions that will be installed in all mappers by default +global_extensions = [] </ins><span class="cx"> </span><span class="cx"> # a constant returned by _getattrbycolumn to indicate </span><span class="cx"> # this mapper is not handling an attribute for a particular </span><span class="lines">@@ -56,13 +56,13 @@ </span><span class="cx"> </span><span class="cx"> ext = MapperExtension() </span><span class="cx"> </span><del>- for ext_class in extensions: </del><ins>+ for ext_class in global_extensions: </ins><span class="cx"> ext = ext_class().chain(ext) </span><ins>+ + for ext_obj in util.to_list(extension): + ext = ext_obj.chain(ext) </ins><span class="cx"> </span><del>- if extension is not None: - self.extension = extension.chain(ext) - else: - self.extension = ext </del><ins>+ self.extension = ext </ins><span class="cx"> </span><span class="cx"> self.class_ = class_ </span><span class="cx"> self.is_primary = is_primary </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymodsselectresultspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py (1229 => 1230)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 07:22:45 UTC (rev 1229) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 07:29:28 UTC (rev 1230) </span><span class="lines">@@ -3,7 +3,7 @@ </span><span class="cx"> import sqlalchemy.mapping as mapping </span><span class="cx"> </span><span class="cx"> def install_plugin(): </span><del>- mapping.extensions.append(SelectResultsExt) </del><ins>+ mapping.global_extensions.append(SelectResultsExt) </ins><span class="cx"> </span><span class="cx"> class SelectResultsExt(mapping.MapperExtension): </span><span class="cx"> def select_by(self, mapper, *args, **params): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-31 07:22:53
|
<!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>[1229] sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py: got install_mods to work</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1229</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-31 01:22:45 -0600 (Fri, 31 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>got install_mods to work</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymods__init__py">sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymods__init__py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py (1228 => 1229)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py 2006-03-31 07:20:13 UTC (rev 1228) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py 2006-03-31 07:22:45 UTC (rev 1229) </span><span class="lines">@@ -1,3 +1,4 @@ </span><span class="cx"> def install_mods(*mods): </span><span class="cx"> for mod in mods: </span><del>- mod.install_plugin() </del><span class="cx">\ No newline at end of file </span><ins>+ _mod = getattr(__import__('sqlalchemy.mods.%s' % mod).mods, mod) + _mod.install_plugin() </ins><span class="cx">\ No newline at end of file </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-31 07:20: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>[1228] sqlalchemy/trunk/test: introducing...the mods package ! the SelectResults thing moves as the first mod</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1228</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-31 01:20:13 -0600 (Fri, 31 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>introducing...the mods package ! the SelectResults thing moves as the first mod</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemy__init__py">sqlalchemy/trunk/lib/sqlalchemy/__init__.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingutilpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> <li><a href="#sqlalchemytrunktestproxy_enginepy">sqlalchemy/trunk/test/proxy_engine.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li>sqlalchemy/trunk/lib/sqlalchemy/mods/</li> <li><a href="#sqlalchemytrunklibsqlalchemymods__init__py">sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymodsselectresultspy">sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemy__init__py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/__init__.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/__init__.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/__init__.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -11,11 +11,12 @@ </span><span class="cx"> from exceptions import * </span><span class="cx"> import mapping as mapperlib </span><span class="cx"> from mapping import * </span><del>- </del><span class="cx"> import sqlalchemy.schema </span><span class="cx"> import sqlalchemy.ext.proxy </span><span class="cx"> sqlalchemy.schema.default_engine = sqlalchemy.ext.proxy.ProxyEngine() </span><span class="cx"> </span><ins>+from sqlalchemy.mods import install_mods + </ins><span class="cx"> def global_connect(*args, **kwargs): </span><span class="cx"> sqlalchemy.schema.default_engine.connect(*args, **kwargs) </span><span class="cx"> </span><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -19,11 +19,17 @@ </span><span class="cx"> # a dictionary mapping classes to their primary mappers </span><span class="cx"> mapper_registry = weakref.WeakKeyDictionary() </span><span class="cx"> </span><ins>+# a list of MapperExtensions that will be installed by default +extensions = [] + </ins><span class="cx"> # a constant returned by _getattrbycolumn to indicate </span><span class="cx"> # this mapper is not handling an attribute for a particular </span><span class="cx"> # column </span><span class="cx"> NO_ATTRIBUTE = object() </span><span class="cx"> </span><ins>+# returned by a MapperExtension method to indicate a "do nothing" response +EXT_PASS = object() + </ins><span class="cx"> class Mapper(object): </span><span class="cx"> """Persists object instances to and from schema.Table objects via the sql package. </span><span class="cx"> Instances of this class should be constructed through this package's mapper() or </span><span class="lines">@@ -47,11 +53,17 @@ </span><span class="cx"> </span><span class="cx"> if primarytable is not None: </span><span class="cx"> sys.stderr.write("'primarytable' argument to mapper is deprecated\n") </span><ins>+ + ext = MapperExtension() + + for ext_class in extensions: + ext = ext_class().chain(ext) </ins><span class="cx"> </span><del>- if extension is None: - self.extension = MapperExtension() </del><ins>+ if extension is not None: + self.extension = extension.chain(ext) </ins><span class="cx"> else: </span><del>- self.extension = extension </del><ins>+ self.extension = ext + </ins><span class="cx"> self.class_ = class_ </span><span class="cx"> self.is_primary = is_primary </span><span class="cx"> self.order_by = order_by </span><span class="lines">@@ -425,7 +437,10 @@ </span><span class="cx"> </span><span class="cx"> e.g. result = usermapper.select_by(user_name = 'fred') </span><span class="cx"> """ </span><del>- return mapperutil.SelectResults(self, self._by_clause(*args, **params)) </del><ins>+ ret = self.extension.select_by(self, *args, **params) + if ret is not EXT_PASS: + return ret + return self.select_whereclause(self._by_clause(*args, **params)) </ins><span class="cx"> </span><span class="cx"> def selectfirst_by(self, *args, **params): </span><span class="cx"> """works like select_by(), but only returns the first result by itself, or None if no </span><span class="lines">@@ -434,7 +449,7 @@ </span><span class="cx"> </span><span class="cx"> def selectone_by(self, *args, **params): </span><span class="cx"> """works like selectfirst_by(), but throws an error if not exactly one result was returned.""" </span><del>- ret = list(self.select_by(*args, **params)[0:2]) </del><ins>+ ret = mapper.select_whereclause(self._by_clause(*args, **params), limit=2) </ins><span class="cx"> if len(ret) == 1: </span><span class="cx"> return ret[0] </span><span class="cx"> raise InvalidRequestError('Multiple rows returned for selectone_by') </span><span class="lines">@@ -510,7 +525,7 @@ </span><span class="cx"> return ret[0] </span><span class="cx"> raise InvalidRequestError('Multiple rows returned for selectone') </span><span class="cx"> </span><del>- def select(self, arg = None, **kwargs): </del><ins>+ def select(self, arg=None, **kwargs): </ins><span class="cx"> """selects instances of the object from the database. </span><span class="cx"> </span><span class="cx"> arg can be any ClauseElement, which will form the criterion with which to </span><span class="lines">@@ -520,10 +535,14 @@ </span><span class="cx"> will be executed and its resulting rowset used to build new object instances. </span><span class="cx"> in this case, the developer must insure that an adequate set of columns exists in the </span><span class="cx"> rowset with which to build new object instances.""" </span><del>- if arg is not None and isinstance(arg, sql.Selectable): </del><ins>+ + ret = self.extension.select(self, arg=arg, **kwargs) + if ret is not EXT_PASS: + return ret + elif arg is not None and isinstance(arg, sql.Selectable): </ins><span class="cx"> return self.select_statement(arg, **kwargs) </span><span class="cx"> else: </span><del>- return mapperutil.SelectResults(self, arg, ops=kwargs) </del><ins>+ return self.select_whereclause(whereclause=arg, **kwargs) </ins><span class="cx"> </span><span class="cx"> def select_whereclause(self, whereclause=None, params=None, **kwargs): </span><span class="cx"> statement = self._compile(whereclause, **kwargs) </span><span class="lines">@@ -850,7 +869,7 @@ </span><span class="cx"> imap[identitykey] = instance </span><span class="cx"> for prop in self.props.values(): </span><span class="cx"> prop.execute(instance, row, identitykey, imap, True) </span><del>- if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </del><ins>+ if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing) is EXT_PASS: </ins><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span><span class="cx"> return instance </span><span class="lines">@@ -865,7 +884,7 @@ </span><span class="cx"> return None </span><span class="cx"> # plugin point </span><span class="cx"> instance = self.extension.create_instance(self, row, imap, self.class_) </span><del>- if instance is None: </del><ins>+ if instance is EXT_PASS: </ins><span class="cx"> instance = self.class_(_mapper_nohistory=True) </span><span class="cx"> imap[identitykey] = instance </span><span class="cx"> isnew = True </span><span class="lines">@@ -877,9 +896,9 @@ </span><span class="cx"> </span><span class="cx"> # call further mapper properties on the row, to pull further </span><span class="cx"> # instances from the row and possibly populate this item. </span><del>- if self.extension.populate_instance(self, instance, row, identitykey, imap, isnew): </del><ins>+ if self.extension.populate_instance(self, instance, row, identitykey, imap, isnew) is EXT_PASS: </ins><span class="cx"> self.populate_instance(instance, row, identitykey, imap, isnew) </span><del>- if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </del><ins>+ if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing) is EXT_PASS: </ins><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span><span class="cx"> return instance </span><span class="lines">@@ -966,6 +985,19 @@ </span><span class="cx"> class MapperExtension(object): </span><span class="cx"> def __init__(self): </span><span class="cx"> self.next = None </span><ins>+ def chain(self, ext): + self.next = ext + return self + def select_by(self, mapper, *args, **kwargs): + if self.next is None: + return EXT_PASS + else: + return self.next.select_by(mapper, *args, **kwargs) + def select(self, mapper, *args, **kwargs): + if self.next is None: + return EXT_PASS + else: + return self.next.select(mapper, *args, **kwargs) </ins><span class="cx"> def create_instance(self, mapper, row, imap, class_): </span><span class="cx"> """called when a new object instance is about to be created from a row. </span><span class="cx"> the method can choose to create the instance itself, or it can return </span><span class="lines">@@ -981,7 +1013,7 @@ </span><span class="cx"> class_ - the class we are mapping. </span><span class="cx"> """ </span><span class="cx"> if self.next is None: </span><del>- return None </del><ins>+ return EXT_PASS </ins><span class="cx"> else: </span><span class="cx"> return self.next.create_instance(mapper, row, imap, class_) </span><span class="cx"> def append_result(self, mapper, row, imap, result, instance, isnew, populate_existing=False): </span><span class="lines">@@ -1011,7 +1043,7 @@ </span><span class="cx"> identity map, i.e. were loaded by a previous select(), get their attributes overwritten </span><span class="cx"> """ </span><span class="cx"> if self.next is None: </span><del>- return True </del><ins>+ return EXT_PASS </ins><span class="cx"> else: </span><span class="cx"> return self.next.append_result(mapper, row, imap, result, instance, isnew, populate_existing) </span><span class="cx"> def populate_instance(self, mapper, instance, row, identitykey, imap, isnew): </span><span class="lines">@@ -1024,10 +1056,10 @@ </span><span class="cx"> </span><span class="cx"> def populate_instance(self, mapper, instance, row, identitykey, imap, isnew): </span><span class="cx"> othermapper.populate_instance(instance, row, identitykey, imap, isnew, frommapper=mapper) </span><del>- return False </del><ins>+ return True </ins><span class="cx"> """ </span><span class="cx"> if self.next is None: </span><del>- return True </del><ins>+ return EXT_PASS </ins><span class="cx"> else: </span><span class="cx"> return self.next.populate_instance(row, imap, result, instance, isnew) </span><span class="cx"> def before_insert(self, mapper, instance): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -382,9 +382,6 @@ </span><span class="cx"> else: </span><span class="cx"> uowcommit.register_dependency(self.mapper, self.parent) </span><span class="cx"> uowcommit.register_processor(self.mapper, self, self.parent, False) </span><del>- # this dependency processor is used to locate "private" child objects - # during a "delete" operation, when the objectstore is being committed - # with only a partial list of objects </del><span class="cx"> uowcommit.register_processor(self.mapper, self, self.parent, True) </span><span class="cx"> else: </span><span class="cx"> raise AssertionError(" no foreign key ?") </span><span class="lines">@@ -616,7 +613,7 @@ </span><span class="cx"> order_by = self.secondary.default_order_by() </span><span class="cx"> else: </span><span class="cx"> order_by = False </span><del>- result = list(self.mapper.select(self.lazywhere, order_by=order_by, params=params)) </del><ins>+ result = self.mapper.select_whereclause(self.lazywhere, order_by=order_by, params=params) </ins><span class="cx"> else: </span><span class="cx"> result = [] </span><span class="cx"> if self.uselist: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingutilpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -1,75 +1,5 @@ </span><span class="cx"> import sqlalchemy.sql as sql </span><span class="cx"> </span><del>-class SelectResults(object): - def __init__(self, mapper, clause=None, ops={}): - self._mapper = mapper - self._clause = clause - self._ops = {} - self._ops.update(ops) - - def count(self): - return self._mapper.count(self._clause) - - def min(self, col): - return sql.select([sql.func.min(col)], self._clause, **self._ops).scalar() - - def max(self, col): - return sql.select([sql.func.max(col)], self._clause, **self._ops).scalar() - - def sum(self, col): - return sql.select([sql.func.sum(col)], self._clause, **self._ops).scalar() - - def avg(self, col): - return sql.select([sql.func.avg(col)], self._clause, **self._ops).scalar() - - def clone(self): - return SelectResults(self._mapper, self._clause, self._ops.copy()) - - def filter(self, clause): - new = self.clone() - new._clause = sql.and_(self._clause, clause) - return new - - def order_by(self, order_by): - new = self.clone() - new._ops['order_by'] = order_by - return new - - def limit(self, limit): - return self[:limit] - - def offset(self, offset): - return self[offset:] - - def list(self): - return list(self) - - def __getitem__(self, item): - if isinstance(item, slice): - start = item.start - stop = item.stop - if (isinstance(start, int) and start < 0) or \ - (isinstance(stop, int) and stop < 0): - return list(self)[item] - else: - res = self.clone() - if start is not None and stop is not None: - res._ops.update(dict(offset=start, limit=stop-start)) - elif start is None and stop is not None: - res._ops.update(dict(limit=stop)) - elif start is not None and stop is None: - res._ops.update(dict(offset=start)) - if item.step is not None: - return list(res)[None:None:item.step] - else: - return res - else: - return list(self[item:item+1])[0] - - def __iter__(self): - return iter(self._mapper.select_whereclause(self._clause, **self._ops)) - - </del><span class="cx"> class TableFinder(sql.ClauseVisitor): </span><span class="cx"> """given a Clause, locates all the Tables within it into a list.""" </span><span class="cx"> def __init__(self, table, check_columns=False): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymods__init__py"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/__init__.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -0,0 +1,3 @@ </span><ins>+def install_mods(*mods): + for mod in mods: + mod.install_plugin() </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymodsselectresultspy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/lib/sqlalchemy/mods/selectresults.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -0,0 +1,84 @@ </span><ins>+import sqlalchemy.sql as sql + +import sqlalchemy.mapping as mapping + +def install_plugin(): + mapping.extensions.append(SelectResultsExt) + +class SelectResultsExt(mapping.MapperExtension): + def select_by(self, mapper, *args, **params): + return SelectResults(mapper, mapper._by_clause(*args, **params)) + def select(self, mapper, arg=None, **kwargs): + if arg is not None and isinstance(arg, sql.Selectable): + return mapping.EXT_PASS + else: + return SelectResults(mapper, arg, ops=kwargs) + +class SelectResults(object): + def __init__(self, mapper, clause=None, ops={}): + self._mapper = mapper + self._clause = clause + self._ops = {} + self._ops.update(ops) + + def count(self): + return self._mapper.count(self._clause) + + def min(self, col): + return sql.select([sql.func.min(col)], self._clause, **self._ops).scalar() + + def max(self, col): + return sql.select([sql.func.max(col)], self._clause, **self._ops).scalar() + + def sum(self, col): + return sql.select([sql.func.sum(col)], self._clause, **self._ops).scalar() + + def avg(self, col): + return sql.select([sql.func.avg(col)], self._clause, **self._ops).scalar() + + def clone(self): + return SelectResults(self._mapper, self._clause, self._ops.copy()) + + def filter(self, clause): + new = self.clone() + new._clause = sql.and_(self._clause, clause) + return new + + def order_by(self, order_by): + new = self.clone() + new._ops['order_by'] = order_by + return new + + def limit(self, limit): + return self[:limit] + + def offset(self, offset): + return self[offset:] + + def list(self): + return list(self) + + def __getitem__(self, item): + if isinstance(item, slice): + start = item.start + stop = item.stop + if (isinstance(start, int) and start < 0) or \ + (isinstance(stop, int) and stop < 0): + return list(self)[item] + else: + res = self.clone() + if start is not None and stop is not None: + res._ops.update(dict(offset=start, limit=stop-start)) + elif start is None and stop is not None: + res._ops.update(dict(limit=stop)) + elif start is not None and stop is None: + res._ops.update(dict(offset=start)) + if item.step is not None: + return list(res)[None:None:item.step] + else: + return res + else: + return list(self[item:item+1])[0] + + def __iter__(self): + return iter(self._mapper.select_whereclause(self._clause, **self._ops)) </ins></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/test/mapper.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -133,7 +133,7 @@ </span><span class="cx"> # object isnt refreshed yet, using dict to bypass trigger </span><span class="cx"> self.assert_(u.__dict__['user_name'] != 'jack') </span><span class="cx"> # do a select </span><del>- m.select().list() </del><ins>+ m.select() </ins><span class="cx"> # test that it refreshed </span><span class="cx"> self.assert_(u.__dict__['user_name'] == 'jack') </span><span class="cx"> </span><span class="lines">@@ -255,7 +255,7 @@ </span><span class="cx"> m = mapper(User, users, properties = dict( </span><span class="cx"> addresses = relation(mapper(Address, addresses), lazy = True) </span><span class="cx"> )) </span><del>- l = m.options(eagerload('addresses')).select().list() </del><ins>+ l = m.options(eagerload('addresses')).select() </ins><span class="cx"> </span><span class="cx"> def go(): </span><span class="cx"> self.assert_result(l, User, *user_address_result) </span><span class="lines">@@ -266,7 +266,7 @@ </span><span class="cx"> m = mapper(User, users, properties = dict( </span><span class="cx"> addresses = relation(mapper(Address, addresses), lazy = False) </span><span class="cx"> )) </span><del>- l = m.options(lazyload('addresses')).select().list() </del><ins>+ l = m.options(lazyload('addresses')).select() </ins><span class="cx"> def go(): </span><span class="cx"> self.assert_result(l, User, *user_address_result) </span><span class="cx"> self.assert_sql_count(db, go, 3) </span><span class="lines">@@ -282,12 +282,12 @@ </span><span class="cx"> }) </span><span class="cx"> </span><span class="cx"> m2 = m.options(eagerload('orders.items.keywords')) </span><del>- u = m.select().list() </del><ins>+ u = m.select() </ins><span class="cx"> def go(): </span><span class="cx"> print u[0].orders[1].items[0].keywords[1] </span><span class="cx"> self.assert_sql_count(db, go, 3) </span><span class="cx"> objectstore.clear() </span><del>- u = m2.select().list() </del><ins>+ u = m2.select() </ins><span class="cx"> self.assert_sql_count(db, go, 2) </span><span class="cx"> </span><span class="cx"> class PropertyTest(MapperSuperTest): </span><span class="lines">@@ -368,7 +368,7 @@ </span><span class="cx"> self.assert_(o.description is None) </span><span class="cx"> </span><span class="cx"> def go(): </span><del>- l = m.select().list() </del><ins>+ l = m.select() </ins><span class="cx"> o2 = l[2] </span><span class="cx"> print o2.description </span><span class="cx"> </span><span class="lines">@@ -397,7 +397,7 @@ </span><span class="cx"> }) </span><span class="cx"> </span><span class="cx"> def go(): </span><del>- l = m.select().list() </del><ins>+ l = m.select() </ins><span class="cx"> o2 = l[2] </span><span class="cx"> print o2.opened, o2.description, o2.userident </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="lines">@@ -410,7 +410,7 @@ </span><span class="cx"> m = mapper(Order, orders) </span><span class="cx"> m2 = m.options(defer('user_id')) </span><span class="cx"> def go(): </span><del>- l = m2.select().list() </del><ins>+ l = m2.select() </ins><span class="cx"> print l[2].user_id </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="cx"> ("SELECT orders.order_id AS orders_order_id, orders.description AS orders_description, orders.isopen AS orders_isopen FROM orders ORDER BY orders.%s" % orders.default_order_by()[0].key, {}), </span><span class="lines">@@ -419,7 +419,7 @@ </span><span class="cx"> objectstore.clear() </span><span class="cx"> m3 = m2.options(undefer('user_id')) </span><span class="cx"> def go(): </span><del>- l = m3.select().list() </del><ins>+ l = m3.select() </ins><span class="cx"> print l[3].user_id </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="cx"> ("SELECT orders.order_id AS orders_order_id, orders.user_id AS orders_user_id, orders.description AS orders_description, orders.isopen AS orders_isopen FROM orders ORDER BY orders.%s" % orders.default_order_by()[0].key, {}), </span></span></pre></div> <a id="sqlalchemytrunktestproxy_enginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/proxy_engine.py (1227 => 1228)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/proxy_engine.py 2006-03-31 04:27:05 UTC (rev 1227) +++ sqlalchemy/trunk/test/proxy_engine.py 2006-03-31 07:20:13 UTC (rev 1228) </span><span class="lines">@@ -96,7 +96,7 @@ </span><span class="cx"> try: </span><span class="cx"> trans = objectstore.begin() </span><span class="cx"> </span><del>- all = User.select()[:].list() </del><ins>+ all = User.select()[:] </ins><span class="cx"> assert all == [] </span><span class="cx"> </span><span class="cx"> u = User() </span></span></pre> </div> </div> </body> </html> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1227] sqlalchemy/trunk/doc/build/content: starting to refactor mapper slightly, adding entity_name, version_id_col, allowing keywords in mapper.options()</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1227</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-30 22:27:05 -0600 (Thu, 30 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>starting to refactor mapper slightly, adding entity_name, version_id_col, allowing keywords in mapper.options()</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentadv_datamappingmyt">sqlalchemy/trunk/doc/build/content/adv_datamapping.myt</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentadv_datamappingmyt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/adv_datamapping.myt (1226 => 1227)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/adv_datamapping.myt 2006-03-31 02:41:32 UTC (rev 1226) +++ sqlalchemy/trunk/doc/build/content/adv_datamapping.myt 2006-03-31 04:27:05 UTC (rev 1227) </span><span class="lines">@@ -314,7 +314,14 @@ </span><span class="cx"> # set the referenced mapper 'photos' to defer its loading of the column 'imagedata' </span><span class="cx"> m = book_mapper.options(defer('photos.imagedata')) </span><span class="cx"> </&> </span><del>- </del><ins>+ <p>Options can also take a limited set of keyword arguments which will be applied to a new mapper. For example, to create a mapper that refreshes all objects loaded each time:</p> + <&|formatting.myt:code&> + m2 = mapper.options(always_refresh=True) + </&> + <p>Or, a mapper with different ordering:</p> + <&|formatting.myt:code&> + m2 = mapper.options(order_by=[newcol]) + </&> </ins><span class="cx"> </span><span class="cx"> </&> </span><span class="cx"> </span><span class="lines">@@ -557,7 +564,16 @@ </span><span class="cx"> address = r[1] </span><span class="cx"> </&> </span><span class="cx"> </&> </span><del>- </del><ins>+<&|doclib.myt:item, name="arguments", description="Mapper Arguments" &> +<p>Other arguments not covered above include:</p> +<ul> + <li>version_id_col=None - an integer-holding Column object that will be assigned an incrementing + counter, which is added to the WHERE clause used by UPDATE and DELETE statements. The matching row + count returned by the database is compared to the expected row count, and an exception is raised if they dont match. This is a basic "optimistic concurrency" check. Without the version id column, SQLAlchemy still compares the updated rowcount.</li> + <li>always_refresh=False - this option will cause the mapper to refresh all the attributes of all objects loaded by select/get statements, regardless of if they already exist in the current session. this includes all lazy- and eager-loaded relationship attributes, and will also overwrite any changes made to attributes on the column.</li> + <li>entity_name=None - this is an optional "entity name" that will be appended to the key used to associate classes to this mapper. What this basically means is, several primary mappers can be made against the same class by using different entity names; object instances will have the entity name tagged to them, so that all operations will occur on them relative to that mapper. When instantiating new objects, use <code>_sa_entity='name'</code> to tag them to the appropriate mapper.</li> +</ul> +</&> </ins><span class="cx"> <&|doclib.myt:item, name="extending", description="Extending Mapper" &> </span><span class="cx"> <p>Mappers can have functionality augmented or replaced at many points in its execution via the usage of the MapperExtension class. This class is just a series of "hooks" where various functionality takes place. An application can make its own MapperExtension objects, overriding only the methods it needs. </span><span class="cx"> <&|formatting.myt:code&> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1226 => 1227)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 02:41:32 UTC (rev 1226) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 04:27:05 UTC (rev 1227) </span><span class="lines">@@ -40,7 +40,9 @@ </span><span class="cx"> extension = None, </span><span class="cx"> order_by = False, </span><span class="cx"> allow_column_override = False, </span><ins>+ entity_name = None, </ins><span class="cx"> always_refresh = False, </span><ins>+ version_id_col = None, </ins><span class="cx"> **kwargs): </span><span class="cx"> </span><span class="cx"> if primarytable is not None: </span><span class="lines">@@ -55,6 +57,8 @@ </span><span class="cx"> self.order_by = order_by </span><span class="cx"> self._options = {} </span><span class="cx"> self.always_refresh = always_refresh </span><ins>+ self.entity_name = entity_name + self.version_id_col = version_id_col </ins><span class="cx"> </span><span class="cx"> if not issubclass(class_, object): </span><span class="cx"> raise ArgumentError("Class '%s' is not a new-style class" % class_.__name__) </span><span class="lines">@@ -85,7 +89,7 @@ </span><span class="cx"> # stricter set of tables to create "sync rules" by,based on the immediate </span><span class="cx"> # inherited table, rather than all inherited tables </span><span class="cx"> self._synchronizer = sync.ClauseSynchronizer(self, self, sync.ONETOMANY) </span><del>- self._synchronizer.compile(self.table.onclause, util.HashSet([inherits.noninherited_table]), TableFinder(table)) </del><ins>+ self._synchronizer.compile(self.table.onclause, util.HashSet([inherits.noninherited_table]), mapperutil.TableFinder(table)) </ins><span class="cx"> # the old rule </span><span class="cx"> #self._synchronizer.compile(self.table.onclause, inherits.tables, TableFinder(table)) </span><span class="cx"> else: </span><span class="lines">@@ -100,7 +104,7 @@ </span><span class="cx"> </span><span class="cx"> # locate all tables contained within the "table" passed in, which </span><span class="cx"> # may be a join or other construct </span><del>- self.tables = TableFinder(self.table) </del><ins>+ self.tables = mapperutil.TableFinder(self.table) </ins><span class="cx"> </span><span class="cx"> # determine primary key columns, either passed in, or get them from our set of tables </span><span class="cx"> self.pks_by_table = {} </span><span class="lines">@@ -350,9 +354,10 @@ </span><span class="cx"> compiling or executing it""" </span><span class="cx"> return self._compile(whereclause, **options) </span><span class="cx"> </span><del>- def copy(self): </del><ins>+ def copy(self, **kwargs): </ins><span class="cx"> mapper = Mapper.__new__(Mapper) </span><span class="cx"> mapper.__dict__.update(self.__dict__) </span><ins>+ mapper.__dict__.update(kwargs) </ins><span class="cx"> mapper.props = self.props.copy() </span><span class="cx"> return mapper </span><span class="cx"> </span><span class="lines">@@ -374,7 +379,7 @@ </span><span class="cx"> return callit </span><span class="cx"> return Proxy() </span><span class="cx"> </span><del>- def options(self, *options): </del><ins>+ def options(self, *options, **kwargs): </ins><span class="cx"> """uses this mapper as a prototype for a new mapper with different behavior. </span><span class="cx"> *options is a list of options directives, which include eagerload(), lazyload(), and noload()""" </span><span class="cx"> </span><span class="lines">@@ -382,7 +387,7 @@ </span><span class="cx"> try: </span><span class="cx"> return self._options[optkey] </span><span class="cx"> except KeyError: </span><del>- mapper = self.copy() </del><ins>+ mapper = self.copy(**kwargs) </ins><span class="cx"> for option in options: </span><span class="cx"> option.process(mapper) </span><span class="cx"> self._options[optkey] = mapper </span><span class="lines">@@ -610,7 +615,13 @@ </span><span class="cx"> self.extension.before_update(self, obj) </span><span class="cx"> hasdata = False </span><span class="cx"> for col in table.columns: </span><del>- if self.pks_by_table[table].contains(col): </del><ins>+ if col is self.version_id_col: + if not isinsert: + params[col._label] = self._getattrbycolumn(obj, col) + params[col.key] = params[col._label] + 1 + else: + params[col.key] = 1 + elif self.pks_by_table[table].contains(col): </ins><span class="cx"> # column is a primary key ? </span><span class="cx"> if not isinsert: </span><span class="cx"> # doing an UPDATE? put primary key values as "WHERE" parameters </span><span class="lines">@@ -664,6 +675,8 @@ </span><span class="cx"> clause = sql.and_() </span><span class="cx"> for col in self.pks_by_table[table]: </span><span class="cx"> clause.clauses.append(col == sql.bindparam(col._label)) </span><ins>+ if self.version_id_col is not None: + clause.clauses.append(self.version_id_col == sql.bindparam(self.version_id_col._label)) </ins><span class="cx"> statement = table.update(clause) </span><span class="cx"> rows = 0 </span><span class="cx"> for rec in update: </span><span class="lines">@@ -729,11 +742,15 @@ </span><span class="cx"> delete.append(params) </span><span class="cx"> for col in self.pks_by_table[table]: </span><span class="cx"> params[col.key] = self._getattrbycolumn(obj, col) </span><ins>+ if self.version_id_col is not None: + params[self.version_id_col.key] = self._getattrbycolumn(obj, self.version_id_col) </ins><span class="cx"> self.extension.before_delete(self, obj) </span><span class="cx"> if len(delete): </span><span class="cx"> clause = sql.and_() </span><span class="cx"> for col in self.pks_by_table[table]: </span><span class="cx"> clause.clauses.append(col == sql.bindparam(col.key)) </span><ins>+ if self.version_id_col is not None: + clause.clauses.append(self.version_id_col == sql.bindparam(self.version_id_col.key)) </ins><span class="cx"> statement = table.delete(clause) </span><span class="cx"> c = statement.execute(*delete) </span><span class="cx"> if table.engine.supports_sane_rowcount() and c.rowcount != len(delete): </span><span class="lines">@@ -1036,28 +1053,6 @@ </span><span class="cx"> if self.next is not None: </span><span class="cx"> self.next.before_delete(mapper, instance) </span><span class="cx"> </span><del>-class TableFinder(sql.ClauseVisitor): - """given a Clause, locates all the Tables within it into a list.""" - def __init__(self, table, check_columns=False): - self.tables = [] - self.check_columns = check_columns - if table is not None: - table.accept_visitor(self) - def visit_table(self, table): - self.tables.append(table) - def __len__(self): - return len(self.tables) - def __getitem__(self, i): - return self.tables[i] - def __iter__(self): - return iter(self.tables) - def __contains__(self, obj): - return obj in self.tables - def __add__(self, obj): - return self.tables + list(obj) - def visit_column(self, column): - if self.check_columns: - column.table.accept_visitor(self) </del><span class="cx"> </span><span class="cx"> def hash_key(obj): </span><span class="cx"> if obj is None: </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-31 02:41:41
|
<!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>[1226] sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py: wow, __len__ is a real disaster when combined with list()...turning that off</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1226</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-30 20:41:32 -0600 (Thu, 30 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>wow, __len__ is a real disaster when combined with list()...turning that off</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingutilpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingutilpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py (1225 => 1226)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-31 02:25:59 UTC (rev 1225) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-31 02:41:32 UTC (rev 1226) </span><span class="lines">@@ -1,4 +1,4 @@ </span><del>-from sqlalchemy.sql import and_, select, func </del><ins>+import sqlalchemy.sql as sql </ins><span class="cx"> </span><span class="cx"> class SelectResults(object): </span><span class="cx"> def __init__(self, mapper, clause=None, ops={}): </span><span class="lines">@@ -10,27 +10,24 @@ </span><span class="cx"> def count(self): </span><span class="cx"> return self._mapper.count(self._clause) </span><span class="cx"> </span><del>- def __len__(self): - return self.count() - </del><span class="cx"> def min(self, col): </span><del>- return select([func.min(col)], self._clause, **self._ops).scalar() </del><ins>+ return sql.select([sql.func.min(col)], self._clause, **self._ops).scalar() </ins><span class="cx"> </span><span class="cx"> def max(self, col): </span><del>- return select([func.max(col)], self._clause, **self._ops).scalar() </del><ins>+ return sql.select([sql.func.max(col)], self._clause, **self._ops).scalar() </ins><span class="cx"> </span><span class="cx"> def sum(self, col): </span><del>- return select([func.sum(col)], self._clause, **self._ops).scalar() </del><ins>+ return sql.select([sql.func.sum(col)], self._clause, **self._ops).scalar() </ins><span class="cx"> </span><span class="cx"> def avg(self, col): </span><del>- return select([func.avg(col)], self._clause, **self._ops).scalar() </del><ins>+ return sql.select([sql.func.avg(col)], self._clause, **self._ops).scalar() </ins><span class="cx"> </span><span class="cx"> def clone(self): </span><span class="cx"> return SelectResults(self._mapper, self._clause, self._ops.copy()) </span><span class="cx"> </span><span class="cx"> def filter(self, clause): </span><span class="cx"> new = self.clone() </span><del>- new._clause = and_(self._clause, clause) </del><ins>+ new._clause = sql.and_(self._clause, clause) </ins><span class="cx"> return new </span><span class="cx"> </span><span class="cx"> def order_by(self, order_by): </span><span class="lines">@@ -70,4 +67,28 @@ </span><span class="cx"> return list(self[item:item+1])[0] </span><span class="cx"> </span><span class="cx"> def __iter__(self): </span><del>- return iter(self._mapper.select_whereclause(self._clause, **self._ops)) </del><span class="cx">\ No newline at end of file </span><ins>+ return iter(self._mapper.select_whereclause(self._clause, **self._ops)) + + +class TableFinder(sql.ClauseVisitor): + """given a Clause, locates all the Tables within it into a list.""" + def __init__(self, table, check_columns=False): + self.tables = [] + self.check_columns = check_columns + if table is not None: + table.accept_visitor(self) + def visit_table(self, table): + self.tables.append(table) + def __len__(self): + return len(self.tables) + def __getitem__(self, i): + return self.tables[i] + def __iter__(self): + return iter(self.tables) + def __contains__(self, obj): + return obj in self.tables + def __add__(self, obj): + return self.tables + list(obj) + def visit_column(self, column): + if self.check_columns: + column.table.accept_visitor(self) </ins></span></pre> </div> </div> </body> </html> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1225] sqlalchemy/trunk/test: Jonas Borgstr?\195?\182m's fantastic SelectRsults patch that adds dynamic list argument support to the mapper.select() methd.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1225</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-30 20:25:59 -0600 (Thu, 30 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>Jonas Borgstr?\195?\182m's fantastic SelectRsults patch that adds dynamic list argument support to the mapper.select() methd. associated unit test tweaks and mapper integration.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunktestalltestspy">sqlalchemy/trunk/test/alltests.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> <li><a href="#sqlalchemytrunktestproxy_enginepy">sqlalchemy/trunk/test/proxy_engine.py</a></li> <li><a href="#sqlalchemytrunktesttestbasepy">sqlalchemy/trunk/test/testbase.py</a></li> </ul> <h3>Added Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingutilpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -9,6 +9,7 @@ </span><span class="cx"> import sqlalchemy.schema as schema </span><span class="cx"> import sqlalchemy.engine as engine </span><span class="cx"> import sqlalchemy.util as util </span><ins>+import util as mapperutil </ins><span class="cx"> import sync </span><span class="cx"> from sqlalchemy.exceptions import * </span><span class="cx"> import objectstore </span><span class="lines">@@ -419,7 +420,7 @@ </span><span class="cx"> </span><span class="cx"> e.g. result = usermapper.select_by(user_name = 'fred') </span><span class="cx"> """ </span><del>- return self.select_whereclause(self._by_clause(*args, **params)) </del><ins>+ return mapperutil.SelectResults(self, self._by_clause(*args, **params)) </ins><span class="cx"> </span><span class="cx"> def selectfirst_by(self, *args, **params): </span><span class="cx"> """works like select_by(), but only returns the first result by itself, or None if no </span><span class="lines">@@ -428,7 +429,7 @@ </span><span class="cx"> </span><span class="cx"> def selectone_by(self, *args, **params): </span><span class="cx"> """works like selectfirst_by(), but throws an error if not exactly one result was returned.""" </span><del>- ret = self.select_by(*args, **params) </del><ins>+ ret = list(self.select_by(*args, **params)[0:2]) </ins><span class="cx"> if len(ret) == 1: </span><span class="cx"> return ret[0] </span><span class="cx"> raise InvalidRequestError('Multiple rows returned for selectone_by') </span><span class="lines">@@ -491,7 +492,7 @@ </span><span class="cx"> """works like select(), but only returns the first result by itself, or None if no </span><span class="cx"> objects returned.""" </span><span class="cx"> params['limit'] = 1 </span><del>- ret = self.select(*args, **params) </del><ins>+ ret = self.select_whereclause(*args, **params) </ins><span class="cx"> if ret: </span><span class="cx"> return ret[0] </span><span class="cx"> else: </span><span class="lines">@@ -499,7 +500,7 @@ </span><span class="cx"> </span><span class="cx"> def selectone(self, *args, **params): </span><span class="cx"> """works like selectfirst(), but throws an error if not exactly one result was returned.""" </span><del>- ret = self.select(*args, **params) </del><ins>+ ret = list(self.select(*args, **params)[0:2]) </ins><span class="cx"> if len(ret) == 1: </span><span class="cx"> return ret[0] </span><span class="cx"> raise InvalidRequestError('Multiple rows returned for selectone') </span><span class="lines">@@ -517,7 +518,7 @@ </span><span class="cx"> if arg is not None and isinstance(arg, sql.Selectable): </span><span class="cx"> return self.select_statement(arg, **kwargs) </span><span class="cx"> else: </span><del>- return self.select_whereclause(arg, **kwargs) </del><ins>+ return mapperutil.SelectResults(self, arg, ops=kwargs) </ins><span class="cx"> </span><span class="cx"> def select_whereclause(self, whereclause=None, params=None, **kwargs): </span><span class="cx"> statement = self._compile(whereclause, **kwargs) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -616,7 +616,7 @@ </span><span class="cx"> order_by = self.secondary.default_order_by() </span><span class="cx"> else: </span><span class="cx"> order_by = False </span><del>- result = self.mapper.select(self.lazywhere, order_by=order_by, params=params) </del><ins>+ result = list(self.mapper.select(self.lazywhere, order_by=order_by, params=params)) </ins><span class="cx"> else: </span><span class="cx"> result = [] </span><span class="cx"> if self.uselist: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingutilpy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/util.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -0,0 +1,73 @@ </span><ins>+from sqlalchemy.sql import and_, select, func + +class SelectResults(object): + def __init__(self, mapper, clause=None, ops={}): + self._mapper = mapper + self._clause = clause + self._ops = {} + self._ops.update(ops) + + def count(self): + return self._mapper.count(self._clause) + + def __len__(self): + return self.count() + + def min(self, col): + return select([func.min(col)], self._clause, **self._ops).scalar() + + def max(self, col): + return select([func.max(col)], self._clause, **self._ops).scalar() + + def sum(self, col): + return select([func.sum(col)], self._clause, **self._ops).scalar() + + def avg(self, col): + return select([func.avg(col)], self._clause, **self._ops).scalar() + + def clone(self): + return SelectResults(self._mapper, self._clause, self._ops.copy()) + + def filter(self, clause): + new = self.clone() + new._clause = and_(self._clause, clause) + return new + + def order_by(self, order_by): + new = self.clone() + new._ops['order_by'] = order_by + return new + + def limit(self, limit): + return self[:limit] + + def offset(self, offset): + return self[offset:] + + def list(self): + return list(self) + + def __getitem__(self, item): + if isinstance(item, slice): + start = item.start + stop = item.stop + if (isinstance(start, int) and start < 0) or \ + (isinstance(stop, int) and stop < 0): + return list(self)[item] + else: + res = self.clone() + if start is not None and stop is not None: + res._ops.update(dict(offset=start, limit=stop-start)) + elif start is None and stop is not None: + res._ops.update(dict(limit=stop)) + elif start is not None and stop is None: + res._ops.update(dict(offset=start)) + if item.step is not None: + return list(res)[None:None:item.step] + else: + return res + else: + return list(self[item:item+1])[0] + + def __iter__(self): + return iter(self._mapper.select_whereclause(self._clause, **self._ops)) </ins><span class="cx">\ No newline at end of file </span></span></pre></div> <a id="sqlalchemytrunktestalltestspy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/alltests.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/alltests.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/test/alltests.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -33,6 +33,7 @@ </span><span class="cx"> </span><span class="cx"> # ORM selecting </span><span class="cx"> 'mapper', </span><ins>+ 'selectresults', </ins><span class="cx"> 'eagertest1', </span><span class="cx"> 'eagertest2', </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/test/mapper.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -133,7 +133,7 @@ </span><span class="cx"> # object isnt refreshed yet, using dict to bypass trigger </span><span class="cx"> self.assert_(u.__dict__['user_name'] != 'jack') </span><span class="cx"> # do a select </span><del>- m.select() </del><ins>+ m.select().list() </ins><span class="cx"> # test that it refreshed </span><span class="cx"> self.assert_(u.__dict__['user_name'] == 'jack') </span><span class="cx"> </span><span class="lines">@@ -255,7 +255,7 @@ </span><span class="cx"> m = mapper(User, users, properties = dict( </span><span class="cx"> addresses = relation(mapper(Address, addresses), lazy = True) </span><span class="cx"> )) </span><del>- l = m.options(eagerload('addresses')).select() </del><ins>+ l = m.options(eagerload('addresses')).select().list() </ins><span class="cx"> </span><span class="cx"> def go(): </span><span class="cx"> self.assert_result(l, User, *user_address_result) </span><span class="lines">@@ -266,7 +266,7 @@ </span><span class="cx"> m = mapper(User, users, properties = dict( </span><span class="cx"> addresses = relation(mapper(Address, addresses), lazy = False) </span><span class="cx"> )) </span><del>- l = m.options(lazyload('addresses')).select() </del><ins>+ l = m.options(lazyload('addresses')).select().list() </ins><span class="cx"> def go(): </span><span class="cx"> self.assert_result(l, User, *user_address_result) </span><span class="cx"> self.assert_sql_count(db, go, 3) </span><span class="lines">@@ -282,12 +282,12 @@ </span><span class="cx"> }) </span><span class="cx"> </span><span class="cx"> m2 = m.options(eagerload('orders.items.keywords')) </span><del>- u = m.select() </del><ins>+ u = m.select().list() </ins><span class="cx"> def go(): </span><span class="cx"> print u[0].orders[1].items[0].keywords[1] </span><span class="cx"> self.assert_sql_count(db, go, 3) </span><span class="cx"> objectstore.clear() </span><del>- u = m2.select() </del><ins>+ u = m2.select().list() </ins><span class="cx"> self.assert_sql_count(db, go, 2) </span><span class="cx"> </span><span class="cx"> class PropertyTest(MapperSuperTest): </span><span class="lines">@@ -368,7 +368,7 @@ </span><span class="cx"> self.assert_(o.description is None) </span><span class="cx"> </span><span class="cx"> def go(): </span><del>- l = m.select() </del><ins>+ l = m.select().list() </ins><span class="cx"> o2 = l[2] </span><span class="cx"> print o2.description </span><span class="cx"> </span><span class="lines">@@ -397,7 +397,7 @@ </span><span class="cx"> }) </span><span class="cx"> </span><span class="cx"> def go(): </span><del>- l = m.select() </del><ins>+ l = m.select().list() </ins><span class="cx"> o2 = l[2] </span><span class="cx"> print o2.opened, o2.description, o2.userident </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="lines">@@ -410,7 +410,7 @@ </span><span class="cx"> m = mapper(Order, orders) </span><span class="cx"> m2 = m.options(defer('user_id')) </span><span class="cx"> def go(): </span><del>- l = m2.select() </del><ins>+ l = m2.select().list() </ins><span class="cx"> print l[2].user_id </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="cx"> ("SELECT orders.order_id AS orders_order_id, orders.description AS orders_description, orders.isopen AS orders_isopen FROM orders ORDER BY orders.%s" % orders.default_order_by()[0].key, {}), </span><span class="lines">@@ -419,7 +419,7 @@ </span><span class="cx"> objectstore.clear() </span><span class="cx"> m3 = m2.options(undefer('user_id')) </span><span class="cx"> def go(): </span><del>- l = m3.select() </del><ins>+ l = m3.select().list() </ins><span class="cx"> print l[3].user_id </span><span class="cx"> self.assert_sql(db, go, [ </span><span class="cx"> ("SELECT orders.order_id AS orders_order_id, orders.user_id AS orders_user_id, orders.description AS orders_description, orders.isopen AS orders_isopen FROM orders ORDER BY orders.%s" % orders.default_order_by()[0].key, {}), </span></span></pre></div> <a id="sqlalchemytrunktestproxy_enginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/proxy_engine.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/proxy_engine.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/test/proxy_engine.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -96,7 +96,7 @@ </span><span class="cx"> try: </span><span class="cx"> trans = objectstore.begin() </span><span class="cx"> </span><del>- all = User.select()[:] </del><ins>+ all = User.select()[:].list() </ins><span class="cx"> assert all == [] </span><span class="cx"> </span><span class="cx"> u = User() </span></span></pre></div> <a id="sqlalchemytrunktesttestbasepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/testbase.py (1224 => 1225)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/testbase.py 2006-03-28 03:07:50 UTC (rev 1224) +++ sqlalchemy/trunk/test/testbase.py 2006-03-31 02:25:59 UTC (rev 1225) </span><span class="lines">@@ -74,6 +74,7 @@ </span><span class="cx"> """given a list-based structure of keys/properties which represent information within an object structure, and </span><span class="cx"> a list of actual objects, asserts that the list of objects corresponds to the structure.""" </span><span class="cx"> def assert_result(self, result, class_, *objects): </span><ins>+ result = list(result) </ins><span class="cx"> if echo: </span><span class="cx"> print repr(result) </span><span class="cx"> self.assert_list(result, class_, objects) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-28 03:08:05
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1224] sqlalchemy/trunk/doc/build/content/metadata.myt: fixed default example</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1224</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-27 21:07:50 -0600 (Mon, 27 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>fixed default example</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontentmetadatamyt">sqlalchemy/trunk/doc/build/content/metadata.myt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontentmetadatamyt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/metadata.myt (1223 => 1224)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/metadata.myt 2006-03-28 02:04:32 UTC (rev 1223) +++ sqlalchemy/trunk/doc/build/content/metadata.myt 2006-03-28 03:07:50 UTC (rev 1224) </span><span class="lines">@@ -139,6 +139,7 @@ </span><span class="cx"> # a function to create primary key ids </span><span class="cx"> i = 0 </span><span class="cx"> def mydefault(): </span><ins>+ global i </ins><span class="cx"> i += 1 </span><span class="cx"> return i </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-28 02:04:45
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1223] sqlalchemy/trunk/lib/sqlalchemy/sql.py: fixed "DISTINCT" spelling</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1223</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-27 20:04:32 -0600 (Mon, 27 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>fixed "DISTINCT" spelling</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1222 => 1223)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-27 03:13:48 UTC (rev 1222) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-28 02:04:32 UTC (rev 1223) </span><span class="lines">@@ -491,7 +491,7 @@ </span><span class="cx"> def label(self, name): </span><span class="cx"> return Label(name, self) </span><span class="cx"> def distinct(self): </span><del>- return CompoundClause(None,"DISTNCT", self) </del><ins>+ return CompoundClause(None,"DISTINCT", self) </ins><span class="cx"> def op(self, operator): </span><span class="cx"> return lambda other: self._compare(operator, other) </span><span class="cx"> # and here come the math operators: </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-27 03:13:58
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1222] sqlalchemy/tags/rel_0_1_5/: 0.1.5</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1222</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 21:13:48 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.1.5</pre> <h3>Added Paths</h3> <ul> <li>sqlalchemy/tags/rel_0_1_5/</li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytagsrel_0_1_5fromrev1221sqlalchemytrunk"></a> <div class="copfile"><h4>Copied: sqlalchemy/tags/rel_0_1_5 (from rev 1221, sqlalchemy/trunk) ( => )</h4> <pre class="diff"><span> <span class="info"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-27 03:12: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>[1221] sqlalchemy/trunk/CHANGES: d</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1221</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 21:12:27 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>d</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 (1220 => 1221)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-03-27 02:58:20 UTC (rev 1220) +++ sqlalchemy/trunk/CHANGES 2006-03-27 03:12:27 UTC (rev 1221) </span><span class="lines">@@ -56,7 +56,6 @@ </span><span class="cx"> work with pysqlite1 </span><span class="cx"> - improvements to subqueries to more intelligently construct their FROM </span><span class="cx"> clauses [ticket:116] </span><del>- </del><span class="cx"> - added PickleType to types. </span><span class="cx"> - fixed two bugs with column labels with regards to bind parameters: bind param </span><span class="cx"> keynames they are now generated from a column "label" in all relevant cases to </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-27 02:58:33
|
<!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>[1220] sqlalchemy/trunk: tweak to mapper to allow inheritance on the same table.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1220</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 20:58:20 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>tweak to mapper to allow inheritance on the same table.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkCHANGES">sqlalchemy/trunk/CHANGES</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkCHANGES"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/CHANGES (1219 => 1220)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-03-27 02:02:06 UTC (rev 1219) +++ sqlalchemy/trunk/CHANGES 2006-03-27 02:58:20 UTC (rev 1220) </span><span class="lines">@@ -31,6 +31,8 @@ </span><span class="cx"> concept of relations on a mapper being made towards the "local" table for that </span><span class="cx"> mapper, not the tables it inherits. allows more complex compositional patterns </span><span class="cx"> to work with lazy/eager loading. </span><ins>+- added support for mappers to inherit from others based on the same table, +just specify the same table as that of both parent/child mapper. </ins><span class="cx"> - some minor speed improvements to the attributes system with regards to </span><span class="cx"> instantiating and populating new objects. </span><span class="cx"> - fixed MySQL binary unit test </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1219 => 1220)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-27 02:02:06 UTC (rev 1219) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-27 02:58:20 UTC (rev 1220) </span><span class="lines">@@ -71,22 +71,24 @@ </span><span class="cx"> if inherits is not None: </span><span class="cx"> self.primarytable = inherits.primarytable </span><span class="cx"> # inherit_condition is optional. </span><del>- if inherit_condition is None: - # figure out inherit condition from our table to the immediate table - # of the inherited mapper, not its full table which could pull in other - # stuff we dont want (allows test/inheritance.InheritTest4 to pass) - inherit_condition = sql.join(inherits.noninherited_table, table).onclause - self.table = sql.join(inherits.table, table, inherit_condition) - #print "inherit condition", str(self.table.onclause) </del><ins>+ if not table is inherits.noninherited_table: + if inherit_condition is None: + # figure out inherit condition from our table to the immediate table + # of the inherited mapper, not its full table which could pull in other + # stuff we dont want (allows test/inheritance.InheritTest4 to pass) + inherit_condition = sql.join(inherits.noninherited_table, table).onclause + self.table = sql.join(inherits.table, table, inherit_condition) + #print "inherit condition", str(self.table.onclause) </ins><span class="cx"> </span><del>- # generate sync rules. similarly to creating the on clause, specify a - # stricter set of tables to create "sync rules" by,based on the immediate - # inherited table, rather than all inherited tables - self._synchronizer = sync.ClauseSynchronizer(self, self, sync.ONETOMANY) - self._synchronizer.compile(self.table.onclause, util.HashSet([inherits.noninherited_table]), TableFinder(table)) - # the old rule - #self._synchronizer.compile(self.table.onclause, inherits.tables, TableFinder(table)) - </del><ins>+ # generate sync rules. similarly to creating the on clause, specify a + # stricter set of tables to create "sync rules" by,based on the immediate + # inherited table, rather than all inherited tables + self._synchronizer = sync.ClauseSynchronizer(self, self, sync.ONETOMANY) + self._synchronizer.compile(self.table.onclause, util.HashSet([inherits.noninherited_table]), TableFinder(table)) + # the old rule + #self._synchronizer.compile(self.table.onclause, inherits.tables, TableFinder(table)) + else: + self._synchronizer = None </ins><span class="cx"> self.inherits = inherits </span><span class="cx"> self.noninherited_table = table </span><span class="cx"> else: </span></span></pre> </div> </div> </body> </html> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1219] sqlalchemy/trunk/test: backrefs on cyclical relationships were breaking for the "root" node which had None for a parent, due to addition in [changeset:1186] which added a "deletion" traversal for many-to-one relationships.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1219</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 20:02:06 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>backrefs on cyclical relationships were breaking for the "root" node which had None for a parent, due to addition in [changeset:1186] which added a "deletion" traversal for many-to-one relationships. added unittest.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py</a></li> <li><a href="#sqlalchemytrunktestcyclespy">sqlalchemy/trunk/test/cycles.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1218 => 1219)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-27 00:51:51 UTC (rev 1218) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-27 02:02:06 UTC (rev 1219) </span><span class="lines">@@ -382,6 +382,9 @@ </span><span class="cx"> else: </span><span class="cx"> uowcommit.register_dependency(self.mapper, self.parent) </span><span class="cx"> uowcommit.register_processor(self.mapper, self, self.parent, False) </span><ins>+ # this dependency processor is used to locate "private" child objects + # during a "delete" operation, when the objectstore is being committed + # with only a partial list of objects </ins><span class="cx"> uowcommit.register_processor(self.mapper, self, self.parent, True) </span><span class="cx"> else: </span><span class="cx"> raise AssertionError(" no foreign key ?") </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py (1218 => 1219)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py 2006-03-27 00:51:51 UTC (rev 1218) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py 2006-03-27 02:02:06 UTC (rev 1219) </span><span class="lines">@@ -647,6 +647,10 @@ </span><span class="cx"> childlist = childlist.added_items() </span><span class="cx"> </span><span class="cx"> for o in childlist: </span><ins>+ if o is None: + # this can be None due to the many-to-one dependency processor added + # for deleted items, line 385 properties.py + continue </ins><span class="cx"> if not o in childtask.objects: </span><span class="cx"> # item needs to be saved since its added, or attached to a deleted object </span><span class="cx"> childtask.append(o, isdelete=isdelete and dep.processor.private) </span></span></pre></div> <a id="sqlalchemytrunktestcyclespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/cycles.py (1218 => 1219)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/cycles.py 2006-03-27 00:51:51 UTC (rev 1218) +++ sqlalchemy/trunk/test/cycles.py 2006-03-27 02:02:06 UTC (rev 1219) </span><span class="lines">@@ -44,6 +44,19 @@ </span><span class="cx"> objectstore.clear() </span><span class="cx"> clear_mappers() </span><span class="cx"> </span><ins>+ def testsingle(self): + class C1(Tester): + pass + m1 = mapper(C1, t1, properties = { + 'c1s':relation(C1, private=True), + 'parent':relation(C1, primaryjoin=t1.c.parent_c1==t1.c.c1, foreignkey=t1.c.c1, lazy=True, uselist=False) + }) + a = C1('head c1') + a.c1s.append(C1('another c1')) + objectstore.commit() + objectstore.delete(a) + objectstore.commit() + </ins><span class="cx"> def testcycle(self): </span><span class="cx"> class C1(Tester): </span><span class="cx"> pass </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-27 00:52:08
|
<!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>[1218] sqlalchemy/trunk: 0.1.5 prep</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1218</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 18:51:51 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>0.1.5 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 (1217 => 1218)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/CHANGES 2006-03-27 00:16:54 UTC (rev 1217) +++ sqlalchemy/trunk/CHANGES 2006-03-27 00:51:51 UTC (rev 1218) </span><span class="lines">@@ -1,15 +1,86 @@ </span><span class="cx"> 0.1.5 </span><ins>+- added SQLSession concept to SQLEngine. this object keeps track of retrieving a +connection from the connection pool as well as an in-progress transaction. +methods push_session() and pop_session() added to SQLEngine which push/pop a new +SQLSession onto the engine, allowing operation upon a second connection "nested" +within the previous one, allowing nested transactions. Other tricks are sure to +come later regarding SQLSession. +- added nest_on argument to objectstore.Session. This is a single SQLEngine or +list of engines for which push_session()/pop_session() will be called each time +this Session becomes the active session (via objectstore.push_session() or +equivalent). This allows a unit of work Session to take advantage of the nested +transaction feature without explicitly calling push_session/pop_session on the +engine. +- factored apart objectstore/unitofwork to separate "Session scoping" from +"uow commit heavy lifting" +- added populate_instance() method to MapperExtension. allows an extension to +modify the population of object attributes. this method can call the +populate_instance() method on another mapper to proxy the attribute population +from one mapper to another; some row translation logic is also built in to help +with this. +- fixed Oracle8-compatibility "use_ansi" flag which converts JOINs to +comparisons with the = and (+) operators, passes basic unittests +- tweaks to Oracle LIMIT/OFFSET support +- Oracle reflection uses ALL_** views instead of USER_** to get larger +list of stuff to reflect from +- fixes to Oracle foreign key reflection [ticket:105] +- objectstore.commit(obj1, obj2,...) adds an extra step to seek out private +relations on properties and delete child objects, even though its not a global +commit +- lots and lots of fixes to mappers which use inheritance, strengthened the +concept of relations on a mapper being made towards the "local" table for that +mapper, not the tables it inherits. allows more complex compositional patterns +to work with lazy/eager loading. +- some minor speed improvements to the attributes system with regards to +instantiating and populating new objects. +- fixed MySQL binary unit test +- INSERTs can receive clause elements as VALUES arguments, not just literal +values +- support for calling multi-tokened functions, i.e. schema.mypkg.func() +- added J. Ellis' SQLSoup module to extensions package +- added "polymorphic" examples illustrating methods to load multiple object types +from one mapper, the second of which uses the new populate_instance() method. +small improvements to mapper, UNION construct to help the examples along +- improvements/fixes to session.refresh()/session.expire() (which may have +been called "invalidate" earlier..) +- added session.expunge() which totally removes an object from the current +session +- added *args, **kwargs pass-thru to engine.transaction(func) allowing easier +creation of transactionalizing decorator functions +- added iterator interface to ResultProxy: "for row in result:..." +- added assertion to tx = session.begin(); tx.rollback(); tx.begin(), i.e. cant +use it after a rollback() +- added date conversion on bind parameter fix to SQLite enabling dates to +work with pysqlite1 +- improvements to subqueries to more intelligently construct their FROM +clauses [ticket:116] + +- added PickleType to types. +- fixed two bugs with column labels with regards to bind parameters: bind param +keynames they are now generated from a column "label" in all relevant cases to +take advantage of excess-name-length rules, and checks for a peculiar collision +against a column named the same as "tablename_colname" added +- major overhaul to unit of work documentation, other documentation sections. </ins><span class="cx"> - fixed attributes bug where if an object is committed, its lazy-loaded list got </span><span class="cx"> blown away if it hadnt been loaded </span><del>-- added unique_connection() method to engine, connection pool to return a connection -that is not part of the thread-local context or any current transaction -- added distinct() function to column elements so you can do func.count(mycol.distinct()) </del><ins>+- added unique_connection() method to engine, connection pool to return a +connection that is not part of the thread-local context or any current +transaction +- added invalidate() function to pooled connection. will remove the connection +from the pool. still need work for engines to auto-reconnect to a stale DB +though. +- added distinct() function to column elements so you can do +func.count(mycol.distinct()) +- added "always_refresh" flag to Mapper, creates a mapper that will always +refresh the attributes of objects it gets/selects from the DB, overwriting any +changes made. </ins><span class="cx"> </span><span class="cx"> 0.1.4 </span><del>-- create_engine() now uses genericized parameters; host/hostname, db/dbname/database, -password/passwd, etc. for all engine connections. makes engine URIs much more "universal" -- added support for SELECT statements embedded into a column clause, using the flag -"scalar=True" </del><ins>+- create_engine() now uses genericized parameters; host/hostname, +db/dbname/database, password/passwd, etc. for all engine connections. makes + engine URIs much more "universal" +- added support for SELECT statements embedded into a column clause, using the +flag "scalar=True" </ins><span class="cx"> - another overhaul to EagerLoading when used in conjunction with mappers that </span><span class="cx"> inherit; improvements to eager loads figuring out their aliased queries </span><span class="cx"> correctly, also relations set up against a mapper with inherited mappers will </span><span class="lines">@@ -28,10 +99,11 @@ </span><span class="cx"> compiled.get_params(), does late-typeprocessing of bind parameters so </span><span class="cx"> that the original values are easier to access </span><span class="cx"> - more docs for indexes, column defaults, connection pooling, engine construction </span><del>-- overhaul to the construction of the types system. uses a simpler inheritance pattern -so that any of the generic types can be easily subclassed, with no need for TypeDecorator. -- added "convert_unicode=False" parameter to SQLEngine, will cause all String types to -perform unicode encoding/decoding (makes Strings act like Unicodes) </del><ins>+- overhaul to the construction of the types system. uses a simpler inheritance +pattern so that any of the generic types can be easily subclassed, with no need +for TypeDecorator. +- added "convert_unicode=False" parameter to SQLEngine, will cause all String +types to perform unicode encoding/decoding (makes Strings act like Unicodes) </ins><span class="cx"> - added 'encoding="utf8"' parameter to engine. the given encoding will be </span><span class="cx"> used for all encode/decode calls within Unicode types as well as Strings </span><span class="cx"> when convert_unicode=True. </span></span></pre></div> <a id="sqlalchemytrunksetuppy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/setup.py (1217 => 1218)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/setup.py 2006-03-27 00:16:54 UTC (rev 1217) +++ sqlalchemy/trunk/setup.py 2006-03-27 00:51:51 UTC (rev 1218) </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.1.4", </del><ins>+ version = "0.1.5", </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-03-27 00:17:05
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1217] sqlalchemy/trunk/TODO: removed..</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1217</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 18:16:54 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>removed..</pre> <h3>Removed Paths</h3> <ul> <li><a href="#sqlalchemytrunkTODO">sqlalchemy/trunk/TODO</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkTODO"></a> <div class="delfile"><h4>Deleted: sqlalchemy/trunk/TODO (1216 => 1217)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/TODO 2006-03-26 23:51:13 UTC (rev 1216) +++ sqlalchemy/trunk/TODO 2006-03-27 00:16:54 UTC (rev 1217) </span><span class="lines">@@ -1,25 +0,0 @@ </span><del>-TODO: - -real exception classes instead of "raise 'string'" - -lazy/eager loaders added to mapper via list arguments instead of dict? - -clean up select test suite - -horizontal lazy loaders - this loads the data from an additional table -into the same object upon hitting any of its properties. - -Oracle module - table reflection - -MySQL module - -INSERT from a SELECT - -generator functions returned from select() to handle [:] slices dynamically ? - -examples - -external functions able to be placed within a UOW's transaction commit; either at the head, or -based on dependencies to other mappers, individual objects - -between() operator </del><span class="cx">\ No newline at end of file </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 23:51:25
|
<!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>[1216] sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py: added always_refresh flag.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1216</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 17:51:13 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>added always_refresh flag. when the mapper loads rows, it will pull objects from the identity map normally, but always blows away their attributes and replaces with those from the database, including changes</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1215 => 1216)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 21:44:22 UTC (rev 1215) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 23:51:13 UTC (rev 1216) </span><span class="lines">@@ -39,6 +39,7 @@ </span><span class="cx"> extension = None, </span><span class="cx"> order_by = False, </span><span class="cx"> allow_column_override = False, </span><ins>+ always_refresh = False, </ins><span class="cx"> **kwargs): </span><span class="cx"> </span><span class="cx"> if primarytable is not None: </span><span class="lines">@@ -52,6 +53,7 @@ </span><span class="cx"> self.is_primary = is_primary </span><span class="cx"> self.order_by = order_by </span><span class="cx"> self._options = {} </span><ins>+ self.always_refresh = always_refresh </ins><span class="cx"> </span><span class="cx"> if not issubclass(class_, object): </span><span class="cx"> raise ArgumentError("Class '%s' is not a new-style class" % class_.__name__) </span><span class="lines">@@ -308,7 +310,7 @@ </span><span class="cx"> return self._get(key, ident) </span><span class="cx"> </span><span class="cx"> def _get(self, key, ident=None, reload=False): </span><del>- if not reload: </del><ins>+ if not reload and not self.always_refresh: </ins><span class="cx"> try: </span><span class="cx"> return objectstore.get_session()._get(key) </span><span class="cx"> except KeyError: </span><span class="lines">@@ -815,6 +817,8 @@ </span><span class="cx"> # look in main identity map. if its there, we dont do anything to it, </span><span class="cx"> # including modifying any of its related items lists, as its already </span><span class="cx"> # been exposed to being modified by the application. </span><ins>+ + populate_existing = populate_existing or self.always_refresh </ins><span class="cx"> identitykey = self._identity_key(row) </span><span class="cx"> sess = objectstore.get_session() </span><span class="cx"> if sess.has_key(identitykey): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 21:44:34
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1215] sqlalchemy/trunk/test: rework to expire() to make it smarter.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1215</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 15:44:22 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>rework to expire() to make it smarter. when you expire(), history is immediately removed as well as explicit from dirty/deleted lists. this also changes uow.rollback_object() to remove from those lists, which is strange that it didnt do that before. anyway the mapper, when selecting and creating instances, asks the uow if this already identity-mapped instance is expired, and if so refreshes it on the fly, saving the need for the re-_get() operation, if some other query happens to touch upon the expired object. unit test added to confirm this.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyattributespy">sqlalchemy/trunk/lib/sqlalchemy/attributes.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingobjectstorepy">sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingunitofworkpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyattributespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/attributes.py (1214 => 1215)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-26 19:58:08 UTC (rev 1214) +++ sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-26 21:44:22 UTC (rev 1215) </span><span class="lines">@@ -398,7 +398,13 @@ </span><span class="cx"> except KeyError: </span><span class="cx"> pass </span><span class="cx"> obj.__dict__['_managed_trigger'] = callable </span><ins>+ + def untrigger_history(self, obj): + del obj.__dict__['_managed_trigger'] </ins><span class="cx"> </span><ins>+ def has_trigger(self, obj): + return obj.__dict__.has_key('_managed_trigger') + </ins><span class="cx"> def reset_history(self, obj, key): </span><span class="cx"> """removes the history object for the given attribute on the given object. </span><span class="cx"> When the attribute is next accessed, a new container will be created via the </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1214 => 1215)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 19:58:08 UTC (rev 1214) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 21:44:22 UTC (rev 1215) </span><span class="lines">@@ -816,16 +816,16 @@ </span><span class="cx"> # including modifying any of its related items lists, as its already </span><span class="cx"> # been exposed to being modified by the application. </span><span class="cx"> identitykey = self._identity_key(row) </span><del>- if objectstore.get_session().has_key(identitykey): - instance = objectstore.get_session()._get(identitykey) </del><ins>+ sess = objectstore.get_session() + if sess.has_key(identitykey): + instance = sess._get(identitykey) </ins><span class="cx"> </span><span class="cx"> isnew = False </span><del>- if populate_existing: </del><ins>+ if populate_existing or sess.is_expired(instance, unexpire=True): </ins><span class="cx"> if not imap.has_key(identitykey): </span><span class="cx"> imap[identitykey] = instance </span><span class="cx"> for prop in self.props.values(): </span><span class="cx"> prop.execute(instance, row, identitykey, imap, True) </span><del>- </del><span class="cx"> if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </span><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingobjectstorepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py (1214 => 1215)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-03-26 19:58:08 UTC (rev 1214) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/objectstore.py 2006-03-26 21:44:22 UTC (rev 1215) </span><span class="lines">@@ -166,7 +166,7 @@ </span><span class="cx"> """invalidates the data in the given objects and sets them to refresh themselves </span><span class="cx"> the next time they are requested.""" </span><span class="cx"> for o in obj: </span><del>- global_attributes.trigger_history(o, lambda: refresh(o)) </del><ins>+ self.uow.expire(o) </ins><span class="cx"> </span><span class="cx"> def expunge(self, *obj): </span><span class="cx"> for o in obj: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingunitofworkpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py (1214 => 1215)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py 2006-03-26 19:58:08 UTC (rev 1214) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/unitofwork.py 2006-03-26 21:44:22 UTC (rev 1215) </span><span class="lines">@@ -100,6 +100,18 @@ </span><span class="cx"> self.rollback_object(obj) </span><span class="cx"> object_mapper(obj)._get(obj._instance_key, reload=True) </span><span class="cx"> </span><ins>+ def expire(self, obj): + self.rollback_object(obj) + def exp(): + object_mapper(obj)._get(obj._instance_key, reload=True) + global_attributes.trigger_history(obj, exp) + + def is_expired(self, obj, unexpire=False): + ret = global_attributes.has_trigger(obj) + if ret and unexpire: + global_attributes.untrigger_history(obj) + return ret + </ins><span class="cx"> def has_key(self, key): </span><span class="cx"> """returns True if the given key is present in this UnitOfWork's identity map.""" </span><span class="cx"> return self.identity_map.has_key(key) </span><span class="lines">@@ -247,6 +259,14 @@ </span><span class="cx"> def rollback_object(self, obj): </span><span class="cx"> """'rolls back' the attributes that have been changed on an object instance.""" </span><span class="cx"> self.attributes.rollback(obj) </span><ins>+ try: + del self.dirty[obj] + except KeyError: + pass + try: + del self.deleted[obj] + except KeyError: + pass </ins><span class="cx"> </span><span class="cx"> class UOWTransaction(object): </span><span class="cx"> """handles the details of organizing and executing transaction tasks </span></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1214 => 1215)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-03-26 19:58:08 UTC (rev 1214) +++ sqlalchemy/trunk/test/mapper.py 2006-03-26 21:44:22 UTC (rev 1215) </span><span class="lines">@@ -111,14 +111,36 @@ </span><span class="cx"> self.assert_(a in u.addresses) </span><span class="cx"> objectstore.expire(u) </span><span class="cx"> </span><del>- # expired, but not refreshed yet. still dirty - self.assert_(u in objectstore.get_session().uow.dirty) </del><span class="cx"> # get the attribute, it refreshes </span><span class="cx"> self.assert_(u.user_name == 'jack') </span><span class="cx"> self.assert_(a not in u.addresses) </span><del>- # not dirty anymore - self.assert_(u not in objectstore.get_session().uow.dirty) - </del><ins>+ + def testexpire(self): + m = mapper(User, users, properties={'addresses':relation(mapper(Address, addresses))}) + u = m.get(7) + u.user_name = 'foo' + objectstore.expire(u) + # test plain expire + self.assert_(u.user_name =='jack') + + # we're changing the database here, so if this test fails in the middle, + # it'll screw up the other tests which are hardcoded to 7/'jack' + u.user_name = 'foo' + objectstore.commit() + # change the value in the DB + users.update(users.c.user_id==7, values=dict(user_name='jack')).execute() + objectstore.expire(u) + # object isnt refreshed yet, using dict to bypass trigger + self.assert_(u.__dict__['user_name'] != 'jack') + # do a select + m.select() + # test that it refreshed + self.assert_(u.__dict__['user_name'] == 'jack') + + # object should be back to normal now, + # this should *not* produce a SELECT statement (not tested here though....) + self.assert_(u.user_name =='jack') + </ins><span class="cx"> def testrefresh2(self): </span><span class="cx"> assign_mapper(Address, addresses) </span><span class="cx"> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 19:58:19
|
<!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>[1214] sqlalchemy/trunk/doc/build/content/types.myt: fixed pickle example, its standard anyway....</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1214</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 13:58:08 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>fixed pickle example, its standard anyway....</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkdocbuildcontenttypesmyt">sqlalchemy/trunk/doc/build/content/types.myt</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkdocbuildcontenttypesmyt"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/doc/build/content/types.myt (1213 => 1214)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/doc/build/content/types.myt 2006-03-26 15:36:43 UTC (rev 1213) +++ sqlalchemy/trunk/doc/build/content/types.myt 2006-03-26 19:58:08 UTC (rev 1214) </span><span class="lines">@@ -39,6 +39,10 @@ </span><span class="cx"> # rowset values, using the unicode encoding </span><span class="cx"> # setting on the engine (defaults to 'utf-8') </span><span class="cx"> class Unicode(String) </span><ins>+ + # uses the pickle protocol to serialize data + # in/out of Binary columns + class PickleType(Binary) </ins><span class="cx"> </&> </span><span class="cx"> <p>More specific subclasses of these types are available, which various database engines may choose to implement specifically, allowing finer grained control over types:</p> </span><span class="cx"> <&|formatting.myt:code&> </span><span class="lines">@@ -87,16 +91,21 @@ </span><span class="cx"> <&|formatting.myt:code, title="Pickle Type"&> </span><span class="cx"> import cPickle </span><span class="cx"> </span><del>- class PickleType(types.Binary): - def __init__(self, protocol=cPickle.HIGHEST_PROTOCOL): </del><ins>+ class PickleType(Binary): + def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): </ins><span class="cx"> """allows the pickle protocol to be specified""" </span><span class="cx"> self.protocol = protocol </span><span class="cx"> def convert_result_value(self, value, engine): </span><del>- return cpickle.loads(super(PickleType, self).convert_result_value(value, engine), self.protocol) </del><ins>+ if value is None: + return None + buf = Binary.convert_result_value(self, value, engine) + return pickle.loads(str(buf)) </ins><span class="cx"> def convert_bind_param(self, value, engine): </span><del>- return super(PickleType, self).convert_bind_param(cpickle.dumps(value, self.protocol), engine) </del><ins>+ if value is None: + return None + return Binary.convert_bind_param(self, pickle.dumps(value, self.protocol), engine) </ins><span class="cx"> def get_constructor_args(self): </span><del>- return {'protocol':self.protocol} </del><ins>+ return {} </ins><span class="cx"> </&> </span><span class="cx"> <p>Which can be used like:</p> </span><span class="cx"> <&|formatting.myt:code&> </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 15:36:55
|
<!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>[1213] sqlalchemy/trunk/lib/sqlalchemy: column label generation checks for a conflict against a column named the same as the label</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1213</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 09:36:43 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>column label generation checks for a conflict against a column named the same as the label comment in mapper</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemysqlpy">sqlalchemy/trunk/lib/sqlalchemy/sql.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1212 => 1213)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 07:21:28 UTC (rev 1212) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 15:36:43 UTC (rev 1213) </span><span class="lines">@@ -998,8 +998,8 @@ </span><span class="cx"> </span><span class="cx"> Essentially, this method is used to have a different mapper populate the object: </span><span class="cx"> </span><del>- def populate_instance(self, mapper, *args): - othermapper.populate_instance(*args) </del><ins>+ def populate_instance(self, mapper, instance, row, identitykey, imap, isnew): + othermapper.populate_instance(instance, row, identitykey, imap, isnew, frommapper=mapper) </ins><span class="cx"> return False </span><span class="cx"> """ </span><span class="cx"> if self.next is None: </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemysqlpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/sql.py (1212 => 1213)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-26 07:21:28 UTC (rev 1212) +++ sqlalchemy/trunk/lib/sqlalchemy/sql.py 2006-03-26 15:36:43 UTC (rev 1213) </span><span class="lines">@@ -1024,7 +1024,7 @@ </span><span class="cx"> self.__label = self.table.name + "_" + self.text </span><span class="cx"> else: </span><span class="cx"> self.__label = self.text </span><del>- if len(self.__label) >= 30: </del><ins>+ if (self.table is not None and self.table.c.has_key(self.__label)) or len(self.__label) >= 30: </ins><span class="cx"> self.__label = self.__label[0:24] + "_" + hex(random.randint(0, 65535))[2:] </span><span class="cx"> return self.__label </span><span class="cx"> _label = property(_get_label) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 07:21:38
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1212] sqlalchemy/trunk/examples/polymorph: improved translation of rows when proxying rows from one mapper to another.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1212</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 01:21:28 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>improved translation of rows when proxying rows from one mapper to another.</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunkexamplespolymorphpolymorph2py">sqlalchemy/trunk/examples/polymorph/polymorph2.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkexamplespolymorphpolymorph2py"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/examples/polymorph/polymorph2.py (1211 => 1212)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/examples/polymorph/polymorph2.py 2006-03-26 06:30:21 UTC (rev 1211) +++ sqlalchemy/trunk/examples/polymorph/polymorph2.py 2006-03-26 07:21:28 UTC (rev 1212) </span><span class="lines">@@ -73,7 +73,8 @@ </span><span class="cx"> column("'engineer'").label('type') </span><span class="cx"> ], </span><span class="cx"> people.c.person_id==engineers.c.person_id)).alias('pjoin') </span><del>- </del><ins>+ +print [c for c in person_join.c] </ins><span class="cx"> </span><span class="cx"> # MapperExtension object. </span><span class="cx"> class PersonLoader(MapperExtension): </span><span class="lines">@@ -87,10 +88,10 @@ </span><span class="cx"> </span><span class="cx"> def populate_instance(self, mapper, instance, row, identitykey, imap, isnew): </span><span class="cx"> if row[person_join.c.type] =='engineer': </span><del>- Engineer.mapper.populate_instance(instance, row, identitykey, imap, isnew) </del><ins>+ Engineer.mapper.populate_instance(instance, row, identitykey, imap, isnew, frommapper=mapper) </ins><span class="cx"> return False </span><span class="cx"> elif row[person_join.c.type] =='manager': </span><del>- Manager.mapper.populate_instance(instance, row, identitykey, imap, isnew) </del><ins>+ Manager.mapper.populate_instance(instance, row, identitykey, imap, isnew, frommapper=mapper) </ins><span class="cx"> return False </span><span class="cx"> else: </span><span class="cx"> return True </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1211 => 1212)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 06:30:21 UTC (rev 1211) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 07:21:28 UTC (rev 1212) </span><span class="lines">@@ -854,19 +854,27 @@ </span><span class="cx"> # call further mapper properties on the row, to pull further </span><span class="cx"> # instances from the row and possibly populate this item. </span><span class="cx"> if self.extension.populate_instance(self, instance, row, identitykey, imap, isnew): </span><del>- self.populate_instance(instance, row, identitykey, imap, isnew, translate=False) </del><ins>+ self.populate_instance(instance, row, identitykey, imap, isnew) </ins><span class="cx"> if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </span><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span><span class="cx"> return instance </span><span class="cx"> </span><del>- def populate_instance(self, instance, row, identitykey, imap, isnew, translate=True): - if translate: - newrow = {} - for table in self.tables: - for c in table.c: - newrow[c] = row[c.key] - row = newrow </del><ins>+ def translate_row(self, tomapper, row): + """attempts to take a row and translate its values to a row that can + be understood by another mapper. breaks the column references down to their + bare keynames to accomplish this. So far this works for the various polymorphic + examples.""" + newrow = util.DictDecorator(row) + for c in self.table.c: + newrow[c.key] = row[c] + for c in tomapper.table.c: + newrow[c] = newrow[c.key] + return newrow + + def populate_instance(self, instance, row, identitykey, imap, isnew, frommapper=None): + if frommapper is not None: + row = frommapper.translate_row(self, row) </ins><span class="cx"> </span><span class="cx"> for prop in self.props.values(): </span><span class="cx"> prop.execute(instance, row, identitykey, imap, isnew) </span></span></pre> </div> </div> </body> </html> |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1211] sqlalchemy/trunk/examples: a cool example that illustrates vertical table storage, and objects that automatically configure themselves for this type of storage</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1211</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 00:30:21 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>a cool example that illustrates vertical table storage, and objects that automatically configure themselves for this type of storage</pre> <h3>Added Paths</h3> <ul> <li>sqlalchemy/trunk/examples/vertical/</li> <li><a href="#sqlalchemytrunkexamplesverticalverticalpy">sqlalchemy/trunk/examples/vertical/vertical.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunkexamplesverticalverticalpy"></a> <div class="addfile"><h4>Added: sqlalchemy/trunk/examples/vertical/vertical.py (1210 => 1211)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/examples/vertical/vertical.py 2006-03-26 06:29:47 UTC (rev 1210) +++ sqlalchemy/trunk/examples/vertical/vertical.py 2006-03-26 06:30:21 UTC (rev 1211) </span><span class="lines">@@ -0,0 +1,164 @@ </span><ins>+from sqlalchemy import * +import datetime + +"""this example illustrates a "vertical table". an object is stored with individual attributes +represented in distinct database rows. This allows objects to be created with dynamically changing +fields that are all persisted in a normalized fashion.""" + +e = create_engine('sqlite://', echo=True) + +# this table represents Entity objects. each Entity gets a row in this table, +# with a primary key and a title. +entities = Table('entities', e, + Column('entity_id', Integer, primary_key=True), + Column('title', String(100), nullable=False), + ).create() + +# this table represents dynamic fields that can be associated +# with values attached to an Entity. +# a field has an ID, a name, and a datatype. +entity_fields = Table('entity_fields', e, + Column('field_id', Integer, primary_key=True), + Column('name', String(40), nullable=False), + Column('datatype', String(30), nullable=False)).create() + +# this table represents attributes that are attached to an +# Entity object. It combines a row from entity_fields with an actual value. +# the value is stored in one of four columns, corresponding to the datatype +# of the field value. +entity_values = Table('entity_values', e, + Column('value_id', Integer, primary_key=True), + Column('field_id', Integer, ForeignKey('entity_fields.field_id'), nullable=False), + Column('entity_id', Integer, ForeignKey('entities.entity_id'), nullable=False), + Column('int_value', Integer), + Column('string_value', String(500)), + Column('binary_value', PickleType), + Column('datetime_value', DateTime)).create() + +class EntityDict(dict): + """this is a dictionary that implements an append() and an __iter__ method. + such a dictionary can be used with SQLAlchemy list-based attributes.""" + def append(self, entityvalue): + self[entityvalue.field.name] = entityvalue + def __iter__(self): + return iter(self.values()) + +class Entity(object): + """represents an Entity. The __getattr__ method is overridden to search the + object's _entities dictionary for the appropriate value, and the __setattribute__ + method is overridden to set all non "_" attributes as EntityValues within the + _entities dictionary. """ + def __init__(self): + """the constructor sets the "_entities" member to an EntityDict. A mapper + will wrap this property with its own history-list object.""" + self._entities = EntityDict() + def __getattr__(self, key): + """getattr proxies requests for attributes which dont 'exist' on the object + to the underying _entities dictionary.""" + try: + return self._entities[key].value + except KeyError: + raise AttributeError(key) + def __setattr__(self, key, value): + """setattr proxies certain requests to set attributes as EntityValues within + the _entities dictionary. This one is tricky as it has to allow underscore attributes, + as well as attributes managed by the Mapper, to be set by default mechanisms. Since the + mapper uses property-like objects on the Entity class to manage attributes, we check + for the key as an attribute of the class and if present, default to normal __setattr__ + mechanisms, else we use the special logic which creates EntityValue objects in the + _entities dictionary.""" + if key[0] == "_" or hasattr(Entity, key): + object.__setattr__(self, key, value) + return + try: + ev = self._entities[key] + ev.value = value + except KeyError: + ev = EntityValue(key, value) + self._entities[key] = ev + +class EntityField(object): + """this class represents a row in the entity_fields table.""" + def __init__(self, name=None): + self.name = name + self.datatype = None + +class EntityValue(object): + """the main job of EntityValue is to hold onto a value, corresponding the type of + the value to the underlying datatype of its EntityField.""" + def __init__(self, key=None, value=None): + if key is not None: + self.field = class_mapper(EntityField).get_by(name=key) or EntityField(key) + if self.field.datatype is None: + if isinstance(value, int): + self.field.datatype = 'int' + elif isinstance(value, str): + self.field.datatype = 'string' + elif isinstance(value, datetime.datetime): + self.field.datatype = 'datetime' + else: + self.field.datatype = 'binary' + setattr(self, self.field.datatype + "_value", value) + def _get_value(self): + return getattr(self, self.field.datatype + "_value") + def _set_value(self, value): + setattr(self, self.field.datatype + "_value", value) + name = property(lambda s: s.field.name) + value = property(_get_value, _set_value) + +# the mappers are a straightforward eager chain of +# Entity--(1->many)->EntityValue-(many->1)->EntityField +# notice that we are identifying each mapper to its connecting +# relation by just the class itself. +mapper(EntityField, entity_fields) +mapper( + EntityValue, entity_values, + properties = { + 'field' : relation(EntityField, lazy=False) + } +) + +entitymapper = mapper(Entity, entities, properties = { + '_entities' : relation(EntityValue, lazy=False) +}) + +# create two entities. the objects can be used about as regularly as +# any object can. +entity = Entity() +entity.title = 'this is the first entity' +entity.name = 'this is the name' +entity.price = 43 +entity.data = ('hello', 'there') + +entity2 = Entity() +entity2.title = 'this is the second entity' +entity2.name = 'this is another name' +entity2.price = 50 +entity2.data = ('hoo', 'ha') + +# commit +objectstore.commit() + +# we would like to illustate loading everything totally clean from +# the database, so we clear out the objectstore. +objectstore.clear() + +# select both objects and print +entities = entitymapper.select() +for entity in entities: + print entity.title, entity.name, entity.price, entity.data + +# now change some data +entities[0].price=90 +entities[0].title = 'another new title' +entities[1].data = {'oof':5,'lala':8} + +# commit changes. the correct rows are updated, nothing else. +objectstore.commit() + +# lets see if that one came through. clear object store, re-select +# and print +objectstore.clear() +entities = entitymapper.select() +for entity in entities: + print entity.title, entity.name, entity.price, entity.data </ins></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 06:29:55
|
<!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>[1210] sqlalchemy/trunk/lib/sqlalchemy/engine.py: except it fails a unit test.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1210</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 00:29:47 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>except it fails a unit test. OK, make it ia KeyError</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyenginepy">sqlalchemy/trunk/lib/sqlalchemy/engine.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyenginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine.py (1209 => 1210)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-26 06:26:02 UTC (rev 1209) +++ sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-26 06:29:47 UTC (rev 1210) </span><span class="lines">@@ -852,10 +852,10 @@ </span><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><del>- #try: - return self.__parent._get_col(self.__row, name) - #except: - # raise AttributeError </del><ins>+ try: + return self.__parent._get_col(self.__row, name) + except KeyError: + raise AttributeError </ins><span class="cx"> def items(self): </span><span class="cx"> return [(key, getattr(self, key)) for key in self.keys()] </span><span class="cx"> def keys(self): </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-26 06:26: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>[1209] sqlalchemy/trunk/lib/sqlalchemy: util: the __setitem__ method on historyarraylist was meaningless, surprising nobody noticed that.</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1209</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-26 00:26:02 -0600 (Sun, 26 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>util: the __setitem__ method on historyarraylist was meaningless, surprising nobody noticed that. types: added PickleType, its slightly trickier than trivial, so OK now its standard. attributes: the level of pain if an AttributeError occurs inside a CallableProp, in combination with an object that implements __getattr__, is too deep for me to put the users through....so convert AttributeErrors to Assertions... engine: im not a fan of catching universal exceptions and squashing them</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyattributespy">sqlalchemy/trunk/lib/sqlalchemy/attributes.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginepy">sqlalchemy/trunk/lib/sqlalchemy/engine.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingmapperpy">sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemytypespy">sqlalchemy/trunk/lib/sqlalchemy/types.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyutilpy">sqlalchemy/trunk/lib/sqlalchemy/util.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyattributespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/attributes.py (1208 => 1209)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-25 21:44:42 UTC (rev 1208) +++ sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-26 06:26:02 UTC (rev 1209) </span><span class="lines">@@ -214,7 +214,12 @@ </span><span class="cx"> if passive: </span><span class="cx"> value = None </span><span class="cx"> else: </span><del>- value = self.callable_() </del><ins>+ try: + value = self.callable_() + except AttributeError, e: + # this catch/raise is because this call is frequently within an + # AttributeError-sensitive callstack + raise AssertionError("AttributeError caught in callable prop:" + str(e.args)) </ins><span class="cx"> self.obj.__dict__[self.key] = value </span><span class="cx"> </span><span class="cx"> p = PropHistory(self.obj, self.key, **self.kwargs) </span><span class="lines">@@ -223,11 +228,15 @@ </span><span class="cx"> if passive: </span><span class="cx"> value = None </span><span class="cx"> else: </span><del>- value = self.callable_() </del><ins>+ try: + value = self.callable_() + except AttributeError, e: + # this catch/raise is because this call is frequently within an + # AttributeError-sensitive callstack + raise AssertionError("AttributeError caught in callable prop:" + str(e.args)) </ins><span class="cx"> else: </span><span class="cx"> value = None </span><span class="cx"> p = self.manager.create_list(self.obj, self.key, value, readonly=self.live, **self.kwargs) </span><del>- </del><span class="cx"> if not self.live and not passive: </span><span class="cx"> # set the new history list as the new attribute, discards ourself </span><span class="cx"> self.manager.attribute_history(self.obj)[self.key] = p </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine.py (1208 => 1209)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-25 21:44:42 UTC (rev 1208) +++ sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-26 06:26:02 UTC (rev 1209) </span><span class="lines">@@ -852,10 +852,10 @@ </span><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><del>- try: - return self.__parent._get_col(self.__row, name) - except: - raise AttributeError </del><ins>+ #try: + return self.__parent._get_col(self.__row, name) + #except: + # raise AttributeError </ins><span class="cx"> def items(self): </span><span class="cx"> return [(key, getattr(self, key)) for key in self.keys()] </span><span class="cx"> def keys(self): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py (1208 => 1209)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-25 21:44:42 UTC (rev 1208) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/mapper.py 2006-03-26 06:26:02 UTC (rev 1209) </span><span class="lines">@@ -812,7 +812,6 @@ </span><span class="cx"> list. if the instance already exists in the given identity map, its not added. in </span><span class="cx"> either case, executes all the property loaders on the instance to also process extra </span><span class="cx"> information in the row.""" </span><del>- </del><span class="cx"> # look in main identity map. if its there, we dont do anything to it, </span><span class="cx"> # including modifying any of its related items lists, as its already </span><span class="cx"> # been exposed to being modified by the application. </span><span class="lines">@@ -830,7 +829,6 @@ </span><span class="cx"> if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </span><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span><del>- </del><span class="cx"> return instance </span><span class="cx"> </span><span class="cx"> # look in result-local identitymap for it. </span><span class="lines">@@ -857,11 +855,9 @@ </span><span class="cx"> # instances from the row and possibly populate this item. </span><span class="cx"> if self.extension.populate_instance(self, instance, row, identitykey, imap, isnew): </span><span class="cx"> self.populate_instance(instance, row, identitykey, imap, isnew, translate=False) </span><del>- </del><span class="cx"> if self.extension.append_result(self, row, imap, result, instance, isnew, populate_existing=populate_existing): </span><span class="cx"> if result is not None: </span><span class="cx"> result.append_nohistory(instance) </span><del>- </del><span class="cx"> return instance </span><span class="cx"> </span><span class="cx"> def populate_instance(self, instance, row, identitykey, imap, isnew, translate=True): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemytypespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/types.py (1208 => 1209)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/types.py 2006-03-25 21:44:42 UTC (rev 1208) +++ sqlalchemy/trunk/lib/sqlalchemy/types.py 2006-03-26 06:26:02 UTC (rev 1209) </span><span class="lines">@@ -7,12 +7,16 @@ </span><span class="cx"> __all__ = [ 'TypeEngine', 'TypeDecorator', 'NullTypeEngine', </span><span class="cx"> 'INT', 'CHAR', 'VARCHAR', 'TEXT', 'FLOAT', 'DECIMAL', </span><span class="cx"> 'TIMESTAMP', 'DATETIME', 'CLOB', 'BLOB', 'BOOLEAN', 'String', 'Integer', 'Smallinteger', </span><del>- 'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'Binary', 'Boolean', 'Unicode', 'NULLTYPE', </del><ins>+ 'Numeric', 'Float', 'DateTime', 'Date', 'Time', 'Binary', 'Boolean', 'Unicode', 'PickleType', 'NULLTYPE', </ins><span class="cx"> 'SMALLINT', 'DATE', 'TIME' </span><span class="cx"> ] </span><span class="cx"> </span><span class="cx"> import sqlalchemy.util as util </span><del>- </del><ins>+try: + import cPickle as pickle +except: + import pickle + </ins><span class="cx"> class TypeEngine(object): </span><span class="cx"> basetypes = [] </span><span class="cx"> def __init__(self, *args, **kwargs): </span><span class="lines">@@ -142,6 +146,22 @@ </span><span class="cx"> def get_constructor_args(self): </span><span class="cx"> return {'length':self.length} </span><span class="cx"> </span><ins>+class PickleType(Binary): + def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): + """allows the pickle protocol to be specified""" + self.protocol = protocol + def convert_result_value(self, value, engine): + if value is None: + return None + buf = Binary.convert_result_value(self, value, engine) + return pickle.loads(str(buf)) + def convert_bind_param(self, value, engine): + if value is None: + return None + return Binary.convert_bind_param(self, pickle.dumps(value, self.protocol), engine) + def get_constructor_args(self): + return {} + </ins><span class="cx"> class Boolean(TypeEngine): </span><span class="cx"> pass </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyutilpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/util.py (1208 => 1209)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/util.py 2006-03-25 21:44:42 UTC (rev 1208) +++ sqlalchemy/trunk/lib/sqlalchemy/util.py 2006-03-26 06:26:02 UTC (rev 1209) </span><span class="lines">@@ -397,7 +397,7 @@ </span><span class="cx"> def has_item(self, item): </span><span class="cx"> return self.records.has_key(item) </span><span class="cx"> def __setitem__(self, i, item): </span><del>- if self._setrecord(a): </del><ins>+ if self._setrecord(item): </ins><span class="cx"> self.data[i] = item </span><span class="cx"> def __delitem__(self, i): </span><span class="cx"> self._delrecord(self.data[i]) </span></span></pre> </div> </div> </body> </html> |
From: <co...@sq...> - 2006-03-25 21:44: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>[1208] sqlalchemy/trunk/test: removed circular loop in creating new list elements, fixes a common refresh() condition</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1208</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-25 15:44:42 -0600 (Sat, 25 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>removed circular loop in creating new list elements, fixes a common refresh() condition added None check in PropertyLoader many-to-one private deletion traversal, fixes byroot_tree (add a unit test for that)</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemyattributespy">sqlalchemy/trunk/lib/sqlalchemy/attributes.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemymappingpropertiespy">sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py</a></li> <li><a href="#sqlalchemytrunktestmapperpy">sqlalchemy/trunk/test/mapper.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemyattributespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/attributes.py (1207 => 1208)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-25 21:14:54 UTC (rev 1207) +++ sqlalchemy/trunk/lib/sqlalchemy/attributes.py 2006-03-25 21:44:42 UTC (rev 1208) </span><span class="lines">@@ -144,6 +144,8 @@ </span><span class="cx"> # list that might be set on the object already </span><span class="cx"> try: </span><span class="cx"> list_ = obj.__dict__[key] </span><ins>+ if list_ is data: + raise InvalidArgumentError("Creating a list element passing the object's list as an argument") </ins><span class="cx"> if data is not None: </span><span class="cx"> for d in data: </span><span class="cx"> list_.append(d) </span><span class="lines">@@ -435,8 +437,7 @@ </span><span class="cx"> elif not uselist: </span><span class="cx"> return PropHistory(obj, key, **kwargs) </span><span class="cx"> else: </span><del>- list_ = obj.__dict__.get(key, None) - return self.create_list(obj, key, list_, **kwargs) </del><ins>+ return self.create_list(obj, key, None, **kwargs) </ins><span class="cx"> </span><span class="cx"> def register_attribute(self, class_, key, uselist, callable_=None, **kwargs): </span><span class="cx"> """registers an attribute's behavior at the class level. This attribute </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemymappingpropertiespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py (1207 => 1208)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-25 21:14:54 UTC (rev 1207) +++ sqlalchemy/trunk/lib/sqlalchemy/mapping/properties.py 2006-03-25 21:44:42 UTC (rev 1208) </span><span class="lines">@@ -449,6 +449,8 @@ </span><span class="cx"> for obj in deplist: </span><span class="cx"> childlist = getlist(obj, False) </span><span class="cx"> for child in childlist.deleted_items() + childlist.unchanged_items(): </span><ins>+ if child is None: + continue </ins><span class="cx"> uowcommit.register_object(child, isdelete=True) </span><span class="cx"> elif self.post_update: </span><span class="cx"> # post_update means we have to update our row to not reference the child object </span><span class="lines">@@ -467,6 +469,8 @@ </span><span class="cx"> for obj in deplist: </span><span class="cx"> childlist = getlist(obj, False) </span><span class="cx"> for child in childlist.deleted_items() + childlist.unchanged_items(): </span><ins>+ if child is None: + continue </ins><span class="cx"> uowcommit.register_object(child, isdelete=True) </span><span class="cx"> else: </span><span class="cx"> for obj in deplist: </span></span></pre></div> <a id="sqlalchemytrunktestmapperpy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/mapper.py (1207 => 1208)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/mapper.py 2006-03-25 21:14:54 UTC (rev 1207) +++ sqlalchemy/trunk/test/mapper.py 2006-03-25 21:44:42 UTC (rev 1208) </span><span class="lines">@@ -118,6 +118,27 @@ </span><span class="cx"> self.assert_(a not in u.addresses) </span><span class="cx"> # not dirty anymore </span><span class="cx"> self.assert_(u not in objectstore.get_session().uow.dirty) </span><ins>+ + def testrefresh2(self): + assign_mapper(Address, addresses) + + assign_mapper(User, users, properties = dict(addresses=relation(Address.mapper,private=True,lazy=False)) ) + + u=User() + u.user_name='Justin' + a = Address() + a.address_id=17 # to work around the hardcoded IDs in this test suite.... + u.addresses.append(a) + objectstore.commit() + objectstore.clear() + u = User.mapper.selectfirst() + print u.user_name + + #ok so far + u.expire() #hangs when + print u.user_name #this line runs + + u.refresh() #hangs </ins><span class="cx"> </span><span class="cx"> def testmagic(self): </span><span class="cx"> m = mapper(User, users, properties = { </span></span></pre> </div> </div> </body> </html> |