<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[12088] twext/trunk/twext/enterprise</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { 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 #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.calendarserver.org//changeset/12088">12088</a></dd>
<dt>Author</dt> <dd>wsanchez@apple.com</dd>
<dt>Date</dt> <dd>2013-12-13 15:59:41 -0800 (Fri, 13 Dec 2013)</dd>
</dl>
<h3>Log Message</h3>
<pre>lint, style</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#twexttrunktwextenterpriseadbapi2py">twext/trunk/twext/enterprise/adbapi2.py</a></li>
<li><a href="#twexttrunktwextenterprisedalmodelpy">twext/trunk/twext/enterprise/dal/model.py</a></li>
<li><a href="#twexttrunktwextenterprisedalparseschemapy">twext/trunk/twext/enterprise/dal/parseschema.py</a></li>
<li><a href="#twexttrunktwextenterprisedalrecordpy">twext/trunk/twext/enterprise/dal/record.py</a></li>
<li><a href="#twexttrunktwextenterprisedalsyntaxpy">twext/trunk/twext/enterprise/dal/syntax.py</a></li>
<li><a href="#twexttrunktwextenterprisedaltesttest_parseschemapy">twext/trunk/twext/enterprise/dal/test/test_parseschema.py</a></li>
<li><a href="#twexttrunktwextenterprisedaltesttest_recordpy">twext/trunk/twext/enterprise/dal/test/test_record.py</a></li>
<li><a href="#twexttrunktwextenterprisedaltesttest_sqlsyntaxpy">twext/trunk/twext/enterprise/dal/test/test_sqlsyntax.py</a></li>
<li><a href="#twexttrunktwextenterprisefixturespy">twext/trunk/twext/enterprise/fixtures.py</a></li>
<li><a href="#twexttrunktwextenterpriseienterprisepy">twext/trunk/twext/enterprise/ienterprise.py</a></li>
<li><a href="#twexttrunktwextenterpriselockingpy">twext/trunk/twext/enterprise/locking.py</a></li>
<li><a href="#twexttrunktwextenterprisequeuepy">twext/trunk/twext/enterprise/queue.py</a></li>
<li><a href="#twexttrunktwextenterprisetesttest_adbapi2py">twext/trunk/twext/enterprise/test/test_adbapi2.py</a></li>
<li><a href="#twexttrunktwextenterprisetesttest_fixturespy">twext/trunk/twext/enterprise/test/test_fixtures.py</a></li>
<li><a href="#twexttrunktwextenterprisetesttest_lockingpy">twext/trunk/twext/enterprise/test/test_locking.py</a></li>
<li><a href="#twexttrunktwextenterprisetesttest_queuepy">twext/trunk/twext/enterprise/test/test_queue.py</a></li>
<li><a href="#twexttrunktwextenterprisetesttest_utilpy">twext/trunk/twext/enterprise/test/test_util.py</a></li>
<li><a href="#twexttrunktwextenterpriseutilpy">twext/trunk/twext/enterprise/util.py</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="twexttrunktwextenterpriseadbapi2py"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/adbapi2.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/adbapi2.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/adbapi2.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx"> # argument to the ConnectionPool but it should probably be determined
</span><span class="cx"> # automatically from the database binding.
</span><span class="cx">
</span><del>-DEFAULT_PARAM_STYLE = 'pyformat'
</del><ins>+DEFAULT_PARAM_STYLE = "pyformat"
</ins><span class="cx"> DEFAULT_DIALECT = POSTGRES_DIALECT
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -185,7 +185,7 @@
</span><span class="cx"> dedicated to and associated with the current cursor. It executes the
</span><span class="cx"> given SQL, re-connecting first if necessary, re-cycling the old
</span><span class="cx"> connection if necessary, and then, if there are results from the
</span><del>- statement (as determined by the DB-API 2.0 'description' attribute) it
</del><ins>+ statement (as determined by the DB-API 2.0 "description" attribute) it
</ins><span class="cx"> will fetch all the rows and return them, leaving them to be relayed to
</span><span class="cx"> L{_ConnectedTxn.execSQL} via the L{ThreadHolder}.
</span><span class="cx">
</span><span class="lines">@@ -224,18 +224,21 @@
</span><span class="cx"> were returned by the executed statement.
</span><span class="cx"> """
</span><span class="cx"> wasFirst = self._first
</span><ins>+
</ins><span class="cx"> # If this is the first time this cursor has been used in this
</span><span class="cx"> # transaction, remember that, but mark it as now used.
</span><span class="cx"> self._first = False
</span><span class="cx"> if args is None:
</span><span class="cx"> args = []
</span><ins>+
</ins><span class="cx"> # Note: as of this writing, derived parameters are only used to support
</span><span class="cx"> # cx_Oracle's "host variable" feature (i.e. cursor.var()), and creating
</span><span class="cx"> # a host variable will never be a connection-oriented error (a
</span><span class="cx"> # disconnected cursor can happily create variables of all types).
</span><del>- # However, this may need to move into the 'try' below if other database
</del><ins>+ # However, this may need to move into the "try" below if other database
</ins><span class="cx"> # features need to compute database arguments based on runtime state.
</span><span class="cx"> derived = _deriveParameters(self._cursor, args)
</span><ins>+
</ins><span class="cx"> try:
</span><span class="cx"> self._cursor.execute(sql, args)
</span><span class="cx"> except:
</span><span class="lines">@@ -263,7 +266,7 @@
</span><span class="cx"> # predictable across different databases, or even different
</span><span class="cx"> # bindings to the same database, so we have to do a
</span><span class="cx"> # catch-all here. While I can't imagine another type of
</span><del>- # error at the moment, bare 'except:'s are notorious for
</del><ins>+ # error at the moment, bare C{except:}s are notorious for
</ins><span class="cx"> # making debugging surprising error conditions very
</span><span class="cx"> # difficult, so let's make sure that the error is logged
</span><span class="cx"> # just in case.
</span><span class="lines">@@ -280,14 +283,16 @@
</span><span class="cx"> self._cursor = self._connection.cursor()
</span><span class="cx">
</span><span class="cx"> # Note that although this method is being invoked recursively,
</span><del>- # the '_first' flag is re-set at the very top, so we will _not_
</del><ins>+ # the "_first" flag is re-set at the very top, so we will _not_
</ins><span class="cx"> # be re-entering it more than once.
</span><span class="cx"> result = self._reallyExecSQL(sql, args, raiseOnZeroRowCount)
</span><span class="cx"> return result
</span><span class="cx"> else:
</span><span class="cx"> raise
</span><ins>+
</ins><span class="cx"> if derived is not None:
</span><span class="cx"> _deriveQueryEnded(self._cursor, derived)
</span><ins>+
</ins><span class="cx"> if self._cursor.description:
</span><span class="cx"> # see test_raiseOnZeroRowCountWithUnreliableRowCount
</span><span class="cx"> rows = self._cursor.fetchall()
</span><span class="lines">@@ -333,6 +338,7 @@
</span><span class="cx"> """
</span><span class="cx"> if not self._completed:
</span><span class="cx"> self._completed = "ended"
</span><ins>+
</ins><span class="cx"> def reallySomething():
</span><span class="cx"> """
</span><span class="cx"> Do the database work and set appropriate flags. Executed in
</span><span class="lines">@@ -342,6 +348,7 @@
</span><span class="cx"> return
</span><span class="cx"> really()
</span><span class="cx"> self._first = True
</span><ins>+
</ins><span class="cx"> result = self._holder.submit(reallySomething)
</span><span class="cx"> self._pool._repoolAfter(self, result)
</span><span class="cx"> return result
</span><span class="lines">@@ -383,6 +390,7 @@
</span><span class="cx"> if self._cursor is None:
</span><span class="cx"> return
</span><span class="cx"> self._connection.close()
</span><ins>+
</ins><span class="cx"> holder.submit(_reallyClose)
</span><span class="cx"> return holder.stop()
</span><span class="cx">
</span><span class="lines">@@ -470,11 +478,11 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def execSQL(self, *a, **kw):
</span><del>- return self._enspool('execSQL', a, kw)
</del><ins>+ return self._enspool("execSQL", a, kw)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def commit(self):
</span><del>- return self._enspool('commit')
</del><ins>+ return self._enspool("commit")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def abort(self):
</span><span class="lines">@@ -538,11 +546,14 @@
</span><span class="cx"> Run pre-hooks, commit, the real DB commit, and then post-hooks.
</span><span class="cx"> """
</span><span class="cx"> pre = self._preCommit.runHooks()
</span><ins>+
</ins><span class="cx"> def ok(ignored):
</span><span class="cx"> self._abort.clear()
</span><span class="cx"> return doCommit().addCallback(self._commit.runHooks)
</span><ins>+
</ins><span class="cx"> def failed(why):
</span><span class="cx"> return self.abort().addCallback(lambda ignored: why)
</span><ins>+
</ins><span class="cx"> return pre.addCallbacks(ok, failed)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -561,7 +572,7 @@
</span><span class="cx">
</span><span class="cx"> class _SingleTxn(_CommitAndAbortHooks,
</span><span class="cx"> proxyForInterface(iface=IAsyncTransaction,
</span><del>- originalAttribute='_baseTxn')):
</del><ins>+ originalAttribute="_baseTxn")):
</ins><span class="cx"> """
</span><span class="cx"> A L{_SingleTxn} is a single-use wrapper for the longer-lived
</span><span class="cx"> L{_ConnectedTxn}, so that if a badly-behaved API client accidentally hangs
</span><span class="lines">@@ -595,7 +606,7 @@
</span><span class="cx"> """
</span><span class="cx"> Reveal the backend in the string representation.
</span><span class="cx"> """
</span><del>- return '_SingleTxn(%r)' % (self._baseTxn,)
</del><ins>+ return "_SingleTxn(%r)" % (self._baseTxn,)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _unspoolOnto(self, baseTxn):
</span><span class="lines">@@ -621,13 +632,15 @@
</span><span class="cx"> self._checkComplete()
</span><span class="cx"> if block is None and self._blockedQueue is not None:
</span><span class="cx"> return self._blockedQueue.execSQL(sql, args, raiseOnZeroRowCount)
</span><del>- # 'block' should always be _currentBlock at this point.
</del><ins>+ # "block" should always be _currentBlock at this point.
</ins><span class="cx"> d = super(_SingleTxn, self).execSQL(sql, args, raiseOnZeroRowCount)
</span><span class="cx"> self._stillExecuting.append(d)
</span><ins>+
</ins><span class="cx"> def itsDone(result):
</span><span class="cx"> self._stillExecuting.remove(d)
</span><span class="cx"> self._checkNextBlock()
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> d.addBoth(itsDone)
</span><span class="cx"> return d
</span><span class="cx">
</span><span class="lines">@@ -640,12 +653,12 @@
</span><span class="cx"> """
</span><span class="cx"> if self._stillExecuting:
</span><span class="cx"> # If we're still executing statements, nevermind. We'll get called
</span><del>- # again by the 'itsDone' callback above.
</del><ins>+ # again by the C{itsDone} callback above.
</ins><span class="cx"> return
</span><span class="cx">
</span><span class="cx"> if self._currentBlock is not None:
</span><span class="cx"> # If there's still a current block, then keep it going. We'll be
</span><del>- # called by the '_finishExecuting' callback below.
</del><ins>+ # called by the C{_finishExecuting} callback below.
</ins><span class="cx"> return
</span><span class="cx">
</span><span class="cx"> # There's no block executing now. What to do?
</span><span class="lines">@@ -679,9 +692,11 @@
</span><span class="cx"> # until they're done. (Commit will be repeated in
</span><span class="cx"> # _checkNextBlock.)
</span><span class="cx"> return self._blockedQueue.commit()
</span><ins>+
</ins><span class="cx"> def reallyCommit():
</span><span class="cx"> self._markComplete()
</span><span class="cx"> return super(_SingleTxn, self).commit()
</span><ins>+
</ins><span class="cx"> return self._commitWithHooks(reallyCommit)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -702,9 +717,11 @@
</span><span class="cx"> """
</span><span class="cx"> self._pool._waiting.remove(self)
</span><span class="cx"> self._completed = True
</span><del>- self._unspoolOnto(_NoTxn(self._pool,
- "connection pool shut down while txn "
- "waiting for database connection."))
</del><ins>+ self._unspoolOnto(_NoTxn(
+ self._pool,
+ "connection pool shut down while txn "
+ "waiting for database connection."
+ ))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _checkComplete(self):
</span><span class="lines">@@ -772,7 +789,7 @@
</span><span class="cx"> Does not implement commit() or abort(), because this will simply group
</span><span class="cx"> commands. In order to implement sub-transactions or checkpoints, some
</span><span class="cx"> understanding of the SQL dialect in use by the underlying connection is
</span><del>- required. Instead, it provides 'end'.
</del><ins>+ required. Instead, it provides C{end}.
</ins><span class="cx"> """
</span><span class="cx"> implements(ICommandBlock)
</span><span class="cx">
</span><span class="lines">@@ -810,14 +827,18 @@
</span><span class="cx"> """
</span><span class="cx"> if track and self._ended:
</span><span class="cx"> raise AlreadyFinishedError()
</span><ins>+
</ins><span class="cx"> self._singleTxn._checkComplete()
</span><ins>+
</ins><span class="cx"> if self._singleTxn._currentBlock is self and self._started:
</span><span class="cx"> d = self._singleTxn._execSQLForBlock(
</span><span class="cx"> sql, args, raiseOnZeroRowCount, self)
</span><span class="cx"> else:
</span><span class="cx"> d = self._spool.execSQL(sql, args, raiseOnZeroRowCount)
</span><ins>+
</ins><span class="cx"> if track:
</span><span class="cx"> self._trackForEnd(d)
</span><ins>+
</ins><span class="cx"> return d
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -840,6 +861,7 @@
</span><span class="cx"> if self._ended:
</span><span class="cx"> raise AlreadyFinishedError()
</span><span class="cx"> self._ended = True
</span><ins>+
</ins><span class="cx"> # TODO: maybe this should return a Deferred that's a clone of
</span><span class="cx"> # _endDeferred, so that callers can determine when the block is really
</span><span class="cx"> # complete? Struggling for an actual use-case on that one.
</span><span class="lines">@@ -885,9 +907,11 @@
</span><span class="cx"> if self._retry is not None:
</span><span class="cx"> self._retry.cancel()
</span><span class="cx"> d = self._holder.stop()
</span><ins>+
</ins><span class="cx"> def removeme(ignored):
</span><span class="cx"> if self in self._pool._busy:
</span><span class="cx"> self._pool._busy.remove(self)
</span><ins>+
</ins><span class="cx"> d.addCallback(removeme)
</span><span class="cx"> return d
</span><span class="cx">
</span><span class="lines">@@ -899,6 +923,7 @@
</span><span class="cx"> disturbing its results.
</span><span class="cx"> """
</span><span class="cx"> d = Deferred()
</span><ins>+
</ins><span class="cx"> def fired(result):
</span><span class="cx"> d.callback(result)
</span><span class="cx"> return result
</span><span class="lines">@@ -952,8 +977,11 @@
</span><span class="cx"> RETRY_TIMEOUT = 10.0
</span><span class="cx">
</span><span class="cx">
</span><del>- def __init__(self, connectionFactory, maxConnections=10,
- paramstyle=DEFAULT_PARAM_STYLE, dialect=DEFAULT_DIALECT):
</del><ins>+ def __init__(
+ self,
+ connectionFactory, maxConnections=10,
+ paramstyle=DEFAULT_PARAM_STYLE, dialect=DEFAULT_DIALECT
+ ):
</ins><span class="cx">
</span><span class="cx"> super(ConnectionPool, self).__init__()
</span><span class="cx"> self.connectionFactory = connectionFactory
</span><span class="lines">@@ -1006,7 +1034,7 @@
</span><span class="cx"> yield self._busy[0].abort()
</span><span class="cx">
</span><span class="cx"> # Phase 4: All transactions should now be in the free list, since
</span><del>- # 'abort()' will have put them there. Shut down all the associated
</del><ins>+ # "abort()" will have put them there. Shut down all the associated
</ins><span class="cx"> # ThreadHolders.
</span><span class="cx"> while self._free:
</span><span class="cx"> # Releasing a L{_ConnectedTxn} doesn't automatically recycle it /
</span><span class="lines">@@ -1039,6 +1067,7 @@
</span><span class="cx"> # FIXME: should be wrapping a _SingleTxn around this to get
</span><span class="cx"> # .commandBlock()
</span><span class="cx"> return _NoTxn(self, "txn created while DB pool shutting down")
</span><ins>+
</ins><span class="cx"> if self._free:
</span><span class="cx"> basetxn = self._free.pop(0)
</span><span class="cx"> self._busy.append(basetxn)
</span><span class="lines">@@ -1050,6 +1079,7 @@
</span><span class="cx"> # (free doesn't need to be considered, as it's tested above)
</span><span class="cx"> if self._activeConnectionCount() < self.maxConnections:
</span><span class="cx"> self._startOneMore()
</span><ins>+
</ins><span class="cx"> return txn
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1067,14 +1097,16 @@
</span><span class="cx"> holder = self._createHolder()
</span><span class="cx"> holder.start()
</span><span class="cx"> txn = _ConnectingPseudoTxn(self, holder)
</span><del>- # take up a slot in the 'busy' list, sit there so we can be aborted.
</del><ins>+ # take up a slot in the "busy" list, sit there so we can be aborted.
</ins><span class="cx"> self._busy.append(txn)
</span><ins>+
</ins><span class="cx"> def initCursor():
</span><span class="cx"> # support threadlevel=1; we can't necessarily cursor() in a
</span><span class="cx"> # different thread than we do transactions in.
</span><span class="cx"> connection = self.connectionFactory()
</span><span class="cx"> cursor = connection.cursor()
</span><span class="cx"> return (connection, cursor)
</span><ins>+
</ins><span class="cx"> def finishInit((connection, cursor)):
</span><span class="cx"> if txn._aborted:
</span><span class="cx"> return
</span><span class="lines">@@ -1086,12 +1118,15 @@
</span><span class="cx"> )
</span><span class="cx"> self._busy.remove(txn)
</span><span class="cx"> self._repoolNow(baseTxn)
</span><ins>+
</ins><span class="cx"> def maybeTryAgain(f):
</span><span class="cx"> log.err(f, "Re-trying connection due to connection failure")
</span><span class="cx"> txn._retry = self.reactor.callLater(self.RETRY_TIMEOUT, resubmit)
</span><ins>+
</ins><span class="cx"> def resubmit():
</span><span class="cx"> d = holder.submit(initCursor)
</span><span class="cx"> d.addCallbacks(finishInit, maybeTryAgain)
</span><ins>+
</ins><span class="cx"> resubmit()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1103,15 +1138,18 @@
</span><span class="cx"> self._busy.remove(txn)
</span><span class="cx"> finishRecord = (txn, d)
</span><span class="cx"> self._finishing.append(finishRecord)
</span><ins>+
</ins><span class="cx"> def repool(result):
</span><span class="cx"> self._finishing.remove(finishRecord)
</span><span class="cx"> self._repoolNow(txn)
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> def discard(result):
</span><span class="cx"> self._finishing.remove(finishRecord)
</span><span class="cx"> txn._releaseConnection()
</span><span class="cx"> self._startOneMore()
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> return d.addCallbacks(repool, discard)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1130,11 +1168,13 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def txnarg():
</span><del>- return [('transactionID', Integer())]
</del><ins>+ return [("transactionID", Integer())]
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> CHUNK_MAX = 0xffff
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class BigArgument(Argument):
</span><span class="cx"> """
</span><span class="cx"> An argument whose payload can be larger than L{CHUNK_MAX}, by splitting
</span><span class="lines">@@ -1162,9 +1202,9 @@
</span><span class="cx">
</span><span class="cx"> class Pickle(BigArgument):
</span><span class="cx"> """
</span><del>- A pickle sent over AMP. This is to serialize the 'args' argument to
- C{execSQL}, which is the dynamically-typed 'args' list argument to a DB-API
- C{execute} function, as well as its dynamically-typed result ('rows').
</del><ins>+ A pickle sent over AMP. This is to serialize the "args" argument to
+ C{execSQL}, which is the dynamically-typed "args" list argument to a DB-API
+ C{execute} function, as well as its dynamically-typed result ("rows").
</ins><span class="cx">
</span><span class="cx"> This should be cleaned up into a nicer structure, but this is not a network
</span><span class="cx"> protocol, so we can be a little relaxed about security.
</span><span class="lines">@@ -1235,11 +1275,13 @@
</span><span class="cx"> """
</span><span class="cx"> Execute an SQL statement.
</span><span class="cx"> """
</span><del>- arguments = [('sql', String()),
- ('queryID', String()),
- ('args', Pickle()),
- ('blockID', String()),
- ('reportZeroRowCount', Boolean())] + txnarg()
</del><ins>+ arguments = [
+ ("sql", String()),
+ ("queryID", String()),
+ ("args", Pickle()),
+ ("blockID", String()),
+ ("reportZeroRowCount", Boolean())
+ ] + txnarg()
</ins><span class="cx"> errors = _quashErrors
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1268,8 +1310,7 @@
</span><span class="cx"> L{ExecSQL}.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- arguments = [('queryID', String()),
- ('row', Pickle())]
</del><ins>+ arguments = [("queryID", String()), ("row", Pickle())]
</ins><span class="cx"> errors = _quashErrors
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1279,10 +1320,12 @@
</span><span class="cx"> A query issued with L{ExecSQL} is complete.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- arguments = [('queryID', String()),
- ('norows', Boolean()),
- ('derived', Pickle()),
- ('noneResult', Boolean())]
</del><ins>+ arguments = [
+ ("queryID", String()),
+ ("norows", Boolean()),
+ ("derived", Pickle()),
+ ("noneResult", Boolean())
+ ]
</ins><span class="cx"> errors = _quashErrors
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1359,19 +1402,23 @@
</span><span class="cx"> reportZeroRowCount):
</span><span class="cx"> derived = None
</span><span class="cx"> noneResult = False
</span><ins>+
</ins><span class="cx"> for param in args:
</span><span class="cx"> if IDerivedParameter.providedBy(param):
</span><span class="cx"> if derived is None:
</span><span class="cx"> derived = []
</span><span class="cx"> derived.append(param)
</span><ins>+
</ins><span class="cx"> if blockID:
</span><span class="cx"> txn = self._blocks[blockID]
</span><span class="cx"> else:
</span><span class="cx"> txn = self._txns[transactionID]
</span><ins>+
</ins><span class="cx"> if reportZeroRowCount:
</span><span class="cx"> rozrc = _NoRows
</span><span class="cx"> else:
</span><span class="cx"> rozrc = None
</span><ins>+
</ins><span class="cx"> try:
</span><span class="cx"> rows = yield txn.execSQL(sql, args, rozrc)
</span><span class="cx"> except _NoRows:
</span><span class="lines">@@ -1386,8 +1433,10 @@
</span><span class="cx"> else:
</span><span class="cx"> noneResult = True
</span><span class="cx">
</span><del>- self.callRemote(QueryComplete, queryID=queryID, norows=norows,
- derived=derived, noneResult=noneResult)
</del><ins>+ self.callRemote(
+ QueryComplete, queryID=queryID, norows=norows,
+ derived=derived, noneResult=noneResult
+ )
</ins><span class="cx"> returnValue({})
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1422,8 +1471,9 @@
</span><span class="cx"> A client which can execute SQL.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def __init__(self, dialect=POSTGRES_DIALECT,
- paramstyle=DEFAULT_PARAM_STYLE):
</del><ins>+ def __init__(
+ self, dialect=POSTGRES_DIALECT, paramstyle=DEFAULT_PARAM_STYLE
+ ):
</ins><span class="cx"> # See DEFAULT_PARAM_STYLE FIXME above.
</span><span class="cx"> super(ConnectionPoolClient, self).__init__()
</span><span class="cx"> self._nextID = count().next
</span><span class="lines">@@ -1511,6 +1561,7 @@
</span><span class="cx"> results = None
</span><span class="cx"> else:
</span><span class="cx"> results = self.results
</span><ins>+
</ins><span class="cx"> if derived is not None:
</span><span class="cx"> # 1) Bleecchh.
</span><span class="cx"> # 2) FIXME: add some direct tests in test_adbapi2, the unit test
</span><span class="lines">@@ -1562,7 +1613,7 @@
</span><span class="cx"> @property
</span><span class="cx"> def paramstyle(self):
</span><span class="cx"> """
</span><del>- Forward 'paramstyle' attribute to the client.
</del><ins>+ Forward C{paramstyle} attribute to the client.
</ins><span class="cx"> """
</span><span class="cx"> return self._client.paramstyle
</span><span class="cx">
</span><span class="lines">@@ -1570,7 +1621,7 @@
</span><span class="cx"> @property
</span><span class="cx"> def dialect(self):
</span><span class="cx"> """
</span><del>- Forward 'dialect' attribute to the client.
</del><ins>+ Forward C{dialect} attribute to the client.
</ins><span class="cx"> """
</span><span class="cx"> return self._client.dialect
</span><span class="cx">
</span><span class="lines">@@ -1608,10 +1659,13 @@
</span><span class="cx"> def commit(self):
</span><span class="cx"> def reallyCommit():
</span><span class="cx"> self._committing = True
</span><ins>+
</ins><span class="cx"> def done(whatever):
</span><span class="cx"> self._committed = True
</span><span class="cx"> return whatever
</span><ins>+
</ins><span class="cx"> return self._complete(Commit).addBoth(done)
</span><ins>+
</ins><span class="cx"> return self._commitWithHooks(reallyCommit)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1658,7 +1712,7 @@
</span><span class="cx"> @property
</span><span class="cx"> def paramstyle(self):
</span><span class="cx"> """
</span><del>- Forward 'paramstyle' attribute to the transaction.
</del><ins>+ Forward C{paramstyle} attribute to the transaction.
</ins><span class="cx"> """
</span><span class="cx"> return self._transaction.paramstyle
</span><span class="cx">
</span><span class="lines">@@ -1666,7 +1720,7 @@
</span><span class="cx"> @property
</span><span class="cx"> def dialect(self):
</span><span class="cx"> """
</span><del>- Forward 'dialect' attribute to the transaction.
</del><ins>+ Forward C{dialect} attribute to the transaction.
</ins><span class="cx"> """
</span><span class="cx"> return self._transaction.dialect
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterprisedalmodelpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/model.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/model.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/model.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -18,17 +18,35 @@
</span><span class="cx"> """
</span><span class="cx"> Model classes for SQL.
</span><span class="cx"> """
</span><ins>+
+__all__ = [
+ "SQLType",
+ "Constraint",
+ "Check",
+ "ProcedureCall",
+ "NO_DEFAULT",
+ "Column",
+ "Table",
+ "Index",
+ "PseudoIndex",
+ "Sequence",
+ "Schema",
+]
+
</ins><span class="cx"> from twisted.python.util import FancyEqMixin
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class SQLType(object):
</span><span class="cx"> """
</span><del>- A data-type as defined in SQL; like "integer" or "real" or "varchar(255)".
</del><ins>+ A data-type as defined in SQL; like C{integer} or C{real} or
+ C{varchar(255)}.
</ins><span class="cx">
</span><span class="cx"> @ivar name: the name of this type.
</span><span class="cx"> @type name: C{str}
</span><span class="cx">
</span><del>- @ivar length: the length of this type, if it is a type like 'varchar' or
- 'character' that comes with a parenthetical length.
</del><ins>+ @ivar length: the length of this type, if it is a type like C{varchar} or
+ C{character} that comes with a parenthetical length.
</ins><span class="cx"> @type length: C{int} or C{NoneType}
</span><span class="cx"> """
</span><span class="cx">
</span><span class="lines">@@ -62,10 +80,10 @@
</span><span class="cx"> present.
</span><span class="cx"> """
</span><span class="cx"> if self.length:
</span><del>- lendesc = '(%s)' % (self.length)
</del><ins>+ lendesc = "(%s)" % (self.length)
</ins><span class="cx"> else:
</span><del>- lendesc = ''
- return '<SQL Type: %r%s>' % (self.name, lendesc)
</del><ins>+ lendesc = ""
+ return "<SQL Type: %r%s>" % (self.name, lendesc)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -73,8 +91,8 @@
</span><span class="cx"> """
</span><span class="cx"> A constraint on a set of columns.
</span><span class="cx">
</span><del>- @ivar type: the type of constraint. Currently, only C{'UNIQUE'} and C{'NOT
- NULL'} are supported.
</del><ins>+ @ivar type: the type of constraint. Currently, only C{"UNIQUE"} and C{"NOT
+ NULL"} are supported.
</ins><span class="cx"> @type type: C{str}
</span><span class="cx">
</span><span class="cx"> @ivar affectsColumns: Columns affected by this constraint.
</span><span class="lines">@@ -82,9 +100,9 @@
</span><span class="cx"> @type affectsColumns: C{list} of L{Column}
</span><span class="cx"> """
</span><span class="cx">
</span><del>- # Values for 'type' attribute:
- NOT_NULL = 'NOT NULL'
- UNIQUE = 'UNIQUE'
</del><ins>+ # Values for "type" attribute:
+ NOT_NULL = "NOT NULL"
+ UNIQUE = "UNIQUE"
</ins><span class="cx">
</span><span class="cx"> def __init__(self, type, affectsColumns, name=None):
</span><span class="cx"> self.affectsColumns = affectsColumns
</span><span class="lines">@@ -97,7 +115,7 @@
</span><span class="cx">
</span><span class="cx"> class Check(Constraint):
</span><span class="cx"> """
</span><del>- A 'check' constraint, which evaluates an SQL expression.
</del><ins>+ A C{check} constraint, which evaluates an SQL expression.
</ins><span class="cx">
</span><span class="cx"> @ivar expression: the expression that should evaluate to True.
</span><span class="cx"> @type expression: L{twext.enterprise.dal.syntax.ExpressionSyntax}
</span><span class="lines">@@ -107,7 +125,7 @@
</span><span class="cx"> def __init__(self, syntaxExpression, name=None):
</span><span class="cx"> self.expression = syntaxExpression
</span><span class="cx"> super(Check, self).__init__(
</span><del>- 'CHECK', [c.model for c in self.expression.allColumns()], name
</del><ins>+ "CHECK", [c.model for c in self.expression.allColumns()], name
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -126,8 +144,8 @@
</span><span class="cx">
</span><span class="cx"> class NO_DEFAULT(object):
</span><span class="cx"> """
</span><del>- Placeholder value for not having a default. (C{None} would not be suitable,
- as that would imply a default of C{NULL}).
</del><ins>+ Placeholder value for not having a default. (C{None} would not be
+ suitable, as that would imply a default of C{NULL}).
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -160,13 +178,14 @@
</span><span class="cx"> this will be a reference to that table; otherwise (normally) C{None}.
</span><span class="cx"> @type references: L{Table} or C{NoneType}
</span><span class="cx">
</span><del>- @ivar deleteAction: If this column references another table, home will this column's
- row be altered when the matching row in that other table is deleted? Possible values are
- None - for 'on delete no action'
- 'cascade' - for 'on delete cascade'
- 'set null' - for 'on delete set null'
- 'set default' - for 'on delete set default'
- @type deleteAction: C{bool}
</del><ins>+ @ivar deleteAction: If this column references another table, home will this
+ column's row be altered when the matching row in that other table is
+ deleted? Possible values are:
+ C{None} - for "on delete no action";
+ C{"cascade"} - for "on delete cascade";
+ C{"set null"} - for "on delete set null";
+ C{"set default"} - for "on delete set default".
+ @type deleteAction: C{str}
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> compareAttributes = 'table name'.split()
</span><span class="lines">@@ -182,7 +201,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return '<Column (%s %r)>' % (self.name, self.type)
</del><ins>+ return "<Column (%s %r)>" % (self.name, self.type)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def compare(self, other):
</span><span class="lines">@@ -196,8 +215,11 @@
</span><span class="cx"> results = []
</span><span class="cx">
</span><span class="cx"> # TODO: sql_dump does not do types write now - so ignore this
</span><del>-# if self.type != other.type:
-# results.append("Table: %s, mismatched column type: %s" % (self.table.name, self.name))
</del><ins>+ # if self.type != other.type:
+ # results.append(
+ # "Table: %s, mismatched column type: %s"
+ # % (self.table.name, self.name)
+ # )
</ins><span class="cx">
</span><span class="cx"> # TODO: figure out how to compare default, references and deleteAction
</span><span class="cx"> return results
</span><span class="lines">@@ -255,7 +277,7 @@
</span><span class="cx"> """
</span><span class="cx"> A set of columns.
</span><span class="cx">
</span><del>- @ivar descriptiveComment: A docstring for the table. Parsed from a '--'
</del><ins>+ @ivar descriptiveComment: A docstring for the table. Parsed from a C{--}
</ins><span class="cx"> comment preceding this table in the SQL schema file that was parsed, if
</span><span class="cx"> any.
</span><span class="cx"> @type descriptiveComment: C{str}
</span><span class="lines">@@ -266,11 +288,11 @@
</span><span class="cx"> key of this table, or C{None} if no primary key has been specified.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- compareAttributes = 'schema name'.split()
</del><ins>+ compareAttributes = "schema name".split()
</ins><span class="cx">
</span><span class="cx"> def __init__(self, schema, name):
</span><span class="cx"> _checkstr(name)
</span><del>- self.descriptiveComment = ''
</del><ins>+ self.descriptiveComment = ""
</ins><span class="cx"> self.schema = schema
</span><span class="cx"> self.name = name
</span><span class="cx"> self.columns = []
</span><span class="lines">@@ -281,7 +303,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return '<Table %r:%r>' % (self.name, self.columns)
</del><ins>+ return "<Table %r:%r>" % (self.name, self.columns)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def compare(self, other):
</span><span class="lines">@@ -295,9 +317,13 @@
</span><span class="cx"> results = []
</span><span class="cx">
</span><span class="cx"> myColumns = dict([(item.name.lower(), item) for item in self.columns])
</span><del>- otherColumns = dict([(item.name.lower(), item) for item in other.columns])
</del><ins>+ otherColumns = dict([
+ (item.name.lower(), item) for item in other.columns
+ ])
</ins><span class="cx"> for item in set(myColumns.keys()) ^ set(otherColumns.keys()):
</span><del>- results.append("Table: %s, missing column: %s" % (self.name, item,))
</del><ins>+ results.append(
+ "Table: %s, missing column: %s" % (self.name, item,)
+ )
</ins><span class="cx">
</span><span class="cx"> for name in set(myColumns.keys()) & set(otherColumns.keys()):
</span><span class="cx"> results.extend(myColumns[name].compare(otherColumns[name]))
</span><span class="lines">@@ -353,8 +379,8 @@
</span><span class="cx">
</span><span class="cx"> def checkConstraint(self, protoExpression, name=None):
</span><span class="cx"> """
</span><del>- This table is affected by a 'check' constraint. (Should only be called
- during schema parsing.)
</del><ins>+ This table is affected by a C{check} constraint. (Should only be
+ called during schema parsing.)
</ins><span class="cx">
</span><span class="cx"> @param protoExpression: proto expression.
</span><span class="cx"> """
</span><span class="lines">@@ -365,8 +391,8 @@
</span><span class="cx"> """
</span><span class="cx"> A statically-defined row was inserted as part of the schema itself.
</span><span class="cx"> This is used for tables that want to track static enumerations, for
</span><del>- example, but want to be referred to by a foreign key in other tables for
- proper referential integrity.
</del><ins>+ example, but want to be referred to by a foreign key in other tables
+ for proper referential integrity.
</ins><span class="cx">
</span><span class="cx"> Append this data to this L{Table}'s L{Table.schemaRows}.
</span><span class="cx">
</span><span class="lines">@@ -424,15 +450,23 @@
</span><span class="cx">
</span><span class="cx"> class PseudoIndex(object):
</span><span class="cx"> """
</span><del>- A class used to represent explicit and implicit indexes. An implicit index is one the
- DB creates for primary key and unique columns in a table. An explicit index is one
- created by a CREATE [UNIQUE] INDEX statement. Because the name of an implicit index
- is implementation defined, instead we create a name based on the table name, uniqueness
- and column names.
</del><ins>+ A class used to represent explicit and implicit indexes. An implicit index
+ is one the DB creates for primary key and unique columns in a table. An
+ explicit index is one created by a CREATE [UNIQUE] INDEX statement. Because
+ the name of an implicit index is implementation-defined, instead we create
+ a name based on the table name, uniqueness and column names.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, table, columns, unique=False):
</span><del>- self.name = "%s%s:(%s)" % (table.name, "-unique" if unique else "", ",".join([col.name for col in columns]))
</del><ins>+ if unique:
+ suffix = "-unique"
+ else:
+ suffix = ""
+
+ self.name = (
+ "%s%s:(%s)"
+ % (table.name, suffix, ",".join([col.name for col in columns]))
+ )
</ins><span class="cx"> self.table = table
</span><span class="cx"> self.unique = unique
</span><span class="cx"> self.columns = columns
</span><span class="lines">@@ -456,7 +490,7 @@
</span><span class="cx"> A sequence object.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- compareAttributes = 'name'.split()
</del><ins>+ compareAttributes = "name".split()
</ins><span class="cx">
</span><span class="cx"> def __init__(self, schema, name):
</span><span class="cx"> _checkstr(name)
</span><span class="lines">@@ -466,7 +500,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return '<Sequence %r>' % (self.name,)
</del><ins>+ return "<Sequence %r>" % (self.name,)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def compare(self, other):
</span><span class="lines">@@ -484,8 +518,8 @@
</span><span class="cx">
</span><span class="cx"> def _namedFrom(name, sequence):
</span><span class="cx"> """
</span><del>- Retrieve an item with a given name attribute from a given sequence, or raise
- a L{KeyError}.
</del><ins>+ Retrieve an item with a given name attribute from a given sequence, or
+ raise a L{KeyError}.
</ins><span class="cx"> """
</span><span class="cx"> for item in sequence:
</span><span class="cx"> if item.name == name:
</span><span class="lines">@@ -499,7 +533,7 @@
</span><span class="cx"> A schema containing tables, indexes, and sequences.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def __init__(self, filename='<string>'):
</del><ins>+ def __init__(self, filename="<string>"):
</ins><span class="cx"> self.filename = filename
</span><span class="cx"> self.tables = []
</span><span class="cx"> self.indexes = []
</span><span class="lines">@@ -507,7 +541,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return '<Schema %r>' % (self.filename,)
</del><ins>+ return "<Schema %r>" % (self.filename,)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def compare(self, other):
</span><span class="lines">@@ -522,11 +556,19 @@
</span><span class="cx">
</span><span class="cx"> def _compareLists(list1, list2, descriptor):
</span><span class="cx"> myItems = dict([(item.name.lower()[:63], item) for item in list1])
</span><del>- otherItems = dict([(item.name.lower()[:63], item) for item in list2])
</del><ins>+ otherItems = dict([
+ (item.name.lower()[:63], item) for item in list2
+ ])
</ins><span class="cx"> for item in set(myItems.keys()) - set(otherItems.keys()):
</span><del>- results.append("Schema: %s, missing %s: %s" % (other.filename, descriptor, item,))
</del><ins>+ results.append(
+ "Schema: %s, missing %s: %s"
+ % (other.filename, descriptor, item)
+ )
</ins><span class="cx"> for item in set(otherItems.keys()) - set(myItems.keys()):
</span><del>- results.append("Schema: %s, missing %s: %s" % (self.filename, descriptor, item,))
</del><ins>+ results.append(
+ "Schema: %s, missing %s: %s"
+ % (self.filename, descriptor, item)
+ )
</ins><span class="cx">
</span><span class="cx"> for name in set(myItems.keys()) & set(otherItems.keys()):
</span><span class="cx"> results.extend(myItems[name].compare(otherItems[name]))
</span><span class="lines">@@ -540,14 +582,17 @@
</span><span class="cx">
</span><span class="cx"> def pseudoIndexes(self):
</span><span class="cx"> """
</span><del>- Return a set of indexes that include "implicit" indexes from table/column constraints. The name of the
- index is formed from the table name and then list of columns.
</del><ins>+ Return a set of indexes that include "implicit" indexes from
+ table/column constraints. The name of the index is formed from the
+ table name and then list of columns.
</ins><span class="cx"> """
</span><span class="cx"> results = []
</span><span class="cx">
</span><span class="cx"> # First add the list of explicit indexes we have
</span><span class="cx"> for index in self.indexes:
</span><del>- results.append(PseudoIndex(index.table, index.columns, index.unique))
</del><ins>+ results.append(
+ PseudoIndex(index.table, index.columns, index.unique)
+ )
</ins><span class="cx">
</span><span class="cx"> # Now do implicit index for each table
</span><span class="cx"> for table in self.tables:
</span><span class="lines">@@ -555,7 +600,9 @@
</span><span class="cx"> results.append(PseudoIndex(table, table.primaryKey, True))
</span><span class="cx"> for constraint in table.constraints:
</span><span class="cx"> if constraint.type == Constraint.UNIQUE:
</span><del>- results.append(PseudoIndex(table, constraint.affectsColumns, True))
</del><ins>+ results.append(
+ PseudoIndex(table, constraint.affectsColumns, True)
+ )
</ins><span class="cx">
</span><span class="cx"> return results
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterprisedalparseschemapy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/parseschema.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/parseschema.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/parseschema.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -20,6 +20,19 @@
</span><span class="cx"> Parser for SQL schema.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+__all__ = [
+ "tableFromCreateStatement",
+ "schemaFromPath",
+ "schemaFromString",
+ "addSQLToSchema",
+ "ViolatedExpectation",
+ "nameOrIdentifier",
+ "expectSingle",
+ "expect",
+ "significant",
+ "iterSignificant",
+]
+
</ins><span class="cx"> from itertools import chain
</span><span class="cx">
</span><span class="cx"> from sqlparse import parse, keywords
</span><span class="lines">@@ -41,12 +54,12 @@
</span><span class="cx"> def _fixKeywords():
</span><span class="cx"> """
</span><span class="cx"> Work around bugs in SQLParse, adding SEQUENCE as a keyword (since it is
</span><del>- treated as one in postgres) and removing ACCESS and SIZE (since we use those
- as column names). Technically those are keywords in SQL, but they aren't
- treated as such by postgres's parser.
</del><ins>+ treated as one in postgres) and removing ACCESS and SIZE (since we use
+ those as column names). Technically those are keywords in SQL, but they
+ aren't treated as such by postgres's parser.
</ins><span class="cx"> """
</span><del>- keywords.KEYWORDS['SEQUENCE'] = Keyword
- for columnNameKeyword in ['ACCESS', 'SIZE']:
</del><ins>+ keywords.KEYWORDS["SEQUENCE"] = Keyword
+ for columnNameKeyword in ["ACCESS", "SIZE"]:
</ins><span class="cx"> del keywords.KEYWORDS[columnNameKeyword]
</span><span class="cx">
</span><span class="cx"> _fixKeywords()
</span><span class="lines">@@ -58,19 +71,17 @@
</span><span class="cx"> Add a table from a CREATE TABLE sqlparse statement object.
</span><span class="cx">
</span><span class="cx"> @param schema: The schema to add the table statement to.
</span><del>-
</del><span class="cx"> @type schema: L{Schema}
</span><span class="cx">
</span><span class="cx"> @param stmt: The C{CREATE TABLE} statement object.
</span><del>-
</del><span class="cx"> @type stmt: L{Statement}
</span><span class="cx"> """
</span><span class="cx"> i = iterSignificant(stmt)
</span><del>- expect(i, ttype=Keyword.DDL, value='CREATE')
- expect(i, ttype=Keyword, value='TABLE')
</del><ins>+ expect(i, ttype=Keyword.DDL, value="CREATE")
+ expect(i, ttype=Keyword, value="TABLE")
</ins><span class="cx"> function = expect(i, cls=Function)
</span><span class="cx"> i = iterSignificant(function)
</span><del>- name = expect(i, cls=Identifier).get_name().encode('utf-8')
</del><ins>+ name = expect(i, cls=Identifier).get_name().encode("utf-8")
</ins><span class="cx"> self = Table(schema, name)
</span><span class="cx"> parens = expect(i, cls=Parenthesis)
</span><span class="cx"> cp = _ColumnParser(self, iterSignificant(parens), parens)
</span><span class="lines">@@ -115,79 +126,105 @@
</span><span class="cx"> Add new SQL to an existing schema.
</span><span class="cx">
</span><span class="cx"> @param schema: The schema to add the new SQL to.
</span><del>-
</del><span class="cx"> @type schema: L{Schema}
</span><span class="cx">
</span><span class="cx"> @param schemaData: A string containing some SQL statements.
</span><del>-
</del><span class="cx"> @type schemaData: C{str}
</span><span class="cx">
</span><span class="cx"> @return: the C{schema} argument
</span><span class="cx"> """
</span><span class="cx"> parsed = parse(schemaData)
</span><ins>+
</ins><span class="cx"> for stmt in parsed:
</span><del>- preface = ''
</del><ins>+ preface = ""
+
</ins><span class="cx"> while stmt.tokens and not significant(stmt.tokens[0]):
</span><span class="cx"> preface += str(stmt.tokens.pop(0))
</span><ins>+
</ins><span class="cx"> if not stmt.tokens:
</span><span class="cx"> continue
</span><del>- if stmt.get_type() == 'CREATE':
</del><ins>+
+ if stmt.get_type() == "CREATE":
</ins><span class="cx"> createType = stmt.token_next(1, True).value.upper()
</span><del>- if createType == u'TABLE':
</del><ins>+
+ if createType == u"TABLE":
</ins><span class="cx"> t = tableFromCreateStatement(schema, stmt)
</span><span class="cx"> t.addComment(preface)
</span><del>- elif createType == u'SEQUENCE':
- Sequence(schema,
- stmt.token_next(2, True).get_name().encode('utf-8'))
- elif createType in (u'INDEX', u'UNIQUE'):
</del><ins>+
+ elif createType == u"SEQUENCE":
+ Sequence(
+ schema,
+ stmt.token_next(2, True).get_name().encode("utf-8")
+ )
+
+ elif createType in (u"INDEX", u"UNIQUE"):
</ins><span class="cx"> signifindex = iterSignificant(stmt)
</span><del>- expect(signifindex, ttype=Keyword.DDL, value='CREATE')
</del><ins>+ expect(signifindex, ttype=Keyword.DDL, value="CREATE")
</ins><span class="cx"> token = signifindex.next()
</span><span class="cx"> unique = False
</span><ins>+
</ins><span class="cx"> if token.match(Keyword, "UNIQUE"):
</span><span class="cx"> unique = True
</span><span class="cx"> token = signifindex.next()
</span><ins>+
</ins><span class="cx"> if not token.match(Keyword, "INDEX"):
</span><span class="cx"> raise ViolatedExpectation("INDEX or UNQIUE", token.value)
</span><ins>+
</ins><span class="cx"> indexName = nameOrIdentifier(signifindex.next())
</span><del>- expect(signifindex, ttype=Keyword, value='ON')
</del><ins>+ expect(signifindex, ttype=Keyword, value="ON")
</ins><span class="cx"> token = signifindex.next()
</span><ins>+
</ins><span class="cx"> if isinstance(token, Function):
</span><span class="cx"> [tableName, columnArgs] = iterSignificant(token)
</span><span class="cx"> else:
</span><span class="cx"> tableName = token
</span><span class="cx"> token = signifindex.next()
</span><ins>+
</ins><span class="cx"> if token.match(Keyword, "USING"):
</span><del>- [_ignore, columnArgs] = iterSignificant(expect(signifindex, cls=Function))
</del><ins>+ [_ignore, columnArgs] = iterSignificant(
+ expect(signifindex, cls=Function)
+ )
</ins><span class="cx"> else:
</span><del>- raise ViolatedExpectation('USING', token)
</del><ins>+ raise ViolatedExpectation("USING", token)
+
</ins><span class="cx"> tableName = nameOrIdentifier(tableName)
</span><span class="cx"> arggetter = iterSignificant(columnArgs)
</span><span class="cx">
</span><del>- expect(arggetter, ttype=Punctuation, value=u'(')
</del><ins>+ expect(arggetter, ttype=Punctuation, value=u"(")
</ins><span class="cx"> valueOrValues = arggetter.next()
</span><ins>+
</ins><span class="cx"> if isinstance(valueOrValues, IdentifierList):
</span><span class="cx"> valuelist = valueOrValues.get_identifiers()
</span><span class="cx"> else:
</span><span class="cx"> valuelist = [valueOrValues]
</span><del>- expect(arggetter, ttype=Punctuation, value=u')')
</del><span class="cx">
</span><del>- idx = Index(schema, indexName, schema.tableNamed(tableName), unique)
</del><ins>+ expect(arggetter, ttype=Punctuation, value=u")")
+
+ idx = Index(
+ schema, indexName, schema.tableNamed(tableName), unique
+ )
+
</ins><span class="cx"> for token in valuelist:
</span><span class="cx"> columnName = nameOrIdentifier(token)
</span><span class="cx"> idx.addColumn(idx.table.columnNamed(columnName))
</span><del>- elif stmt.get_type() == 'INSERT':
</del><ins>+
+ elif stmt.get_type() == "INSERT":
</ins><span class="cx"> insertTokens = iterSignificant(stmt)
</span><del>- expect(insertTokens, ttype=Keyword.DML, value='INSERT')
- expect(insertTokens, ttype=Keyword, value='INTO')
</del><ins>+ expect(insertTokens, ttype=Keyword.DML, value="INSERT")
+ expect(insertTokens, ttype=Keyword, value="INTO")
+
</ins><span class="cx"> tableName = expect(insertTokens, cls=Identifier).get_name()
</span><del>- expect(insertTokens, ttype=Keyword, value='VALUES')
</del><ins>+ expect(insertTokens, ttype=Keyword, value="VALUES")
+
</ins><span class="cx"> values = expect(insertTokens, cls=Parenthesis)
</span><span class="cx"> vals = iterSignificant(values)
</span><del>- expect(vals, ttype=Punctuation, value='(')
</del><ins>+ expect(vals, ttype=Punctuation, value="(")
+
</ins><span class="cx"> valuelist = expect(vals, cls=IdentifierList)
</span><del>- expect(vals, ttype=Punctuation, value=')')
</del><ins>+ expect(vals, ttype=Punctuation, value=")")
+
</ins><span class="cx"> rowData = []
</span><ins>+
</ins><span class="cx"> for ident in valuelist.get_identifiers():
</span><span class="cx"> rowData.append(
</span><span class="cx"> {Number.Integer: int,
</span><span class="lines">@@ -196,8 +233,10 @@
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> schema.tableNamed(tableName).insertSchemaRow(rowData)
</span><ins>+
</ins><span class="cx"> else:
</span><del>- print('unknown type:', stmt.get_type())
</del><ins>+ print("unknown type:", stmt.get_type())
+
</ins><span class="cx"> return schema
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -276,12 +315,14 @@
</span><span class="cx"> parens = iterSignificant(parens)
</span><span class="cx"> expect(parens, ttype=Punctuation, value="(")
</span><span class="cx"> idorids = parens.next()
</span><ins>+
</ins><span class="cx"> if isinstance(idorids, Identifier):
</span><span class="cx"> idnames = [idorids.get_name()]
</span><span class="cx"> elif isinstance(idorids, IdentifierList):
</span><span class="cx"> idnames = [x.get_name() for x in idorids.get_identifiers()]
</span><span class="cx"> else:
</span><span class="cx"> raise ViolatedExpectation("identifier or list", repr(idorids))
</span><ins>+
</ins><span class="cx"> expect(parens, ttype=Punctuation, value=")")
</span><span class="cx"> return idnames
</span><span class="cx">
</span><span class="lines">@@ -295,11 +336,15 @@
</span><span class="cx"> parens = iterSignificant(parens)
</span><span class="cx"> expect(parens, ttype=Punctuation, value="(")
</span><span class="cx"> nexttok = parens.next()
</span><ins>+
</ins><span class="cx"> if isinstance(nexttok, Comparison):
</span><span class="cx"> lhs, op, rhs = list(iterSignificant(nexttok))
</span><del>- result = CompoundComparison(self.nameOrValue(lhs),
- op.value.encode("ascii"),
- self.nameOrValue(rhs))
</del><ins>+ result = CompoundComparison(
+ self.nameOrValue(lhs),
+ op.value.encode("ascii"),
+ self.nameOrValue(rhs)
+ )
+
</ins><span class="cx"> elif isinstance(nexttok, Identifier):
</span><span class="cx"> # our version of SQLParse seems to break down and not create a nice
</span><span class="cx"> # "Comparison" object when a keyword is present. This is just a
</span><span class="lines">@@ -331,26 +376,29 @@
</span><span class="cx">
</span><span class="cx"> def parseConstraint(self, constraintType):
</span><span class="cx"> """
</span><del>- Parse a 'free' constraint, described explicitly in the table as opposed
- to being implicitly associated with a column by being placed after it.
</del><ins>+ Parse a C{free} constraint, described explicitly in the table as
+ opposed to being implicitly associated with a column by being placed
+ after it.
</ins><span class="cx"> """
</span><span class="cx"> ident = None
</span><span class="cx"> # TODO: make use of identifier in tableConstraint, currently only used
</span><span class="cx"> # for checkConstraint.
</span><del>- if constraintType.match(Keyword, 'CONSTRAINT'):
</del><ins>+ if constraintType.match(Keyword, "CONSTRAINT"):
</ins><span class="cx"> ident = expect(self, cls=Identifier).get_name()
</span><span class="cx"> constraintType = expect(self, ttype=Keyword)
</span><del>- if constraintType.match(Keyword, 'PRIMARY'):
- expect(self, ttype=Keyword, value='KEY')
</del><ins>+
+ if constraintType.match(Keyword, "PRIMARY"):
+ expect(self, ttype=Keyword, value="KEY")
</ins><span class="cx"> names = self.namesInParens(expect(self, cls=Parenthesis))
</span><span class="cx"> self.table.primaryKey = [self.table.columnNamed(n) for n in names]
</span><del>- elif constraintType.match(Keyword, 'UNIQUE'):
</del><ins>+ elif constraintType.match(Keyword, "UNIQUE"):
</ins><span class="cx"> names = self.namesInParens(expect(self, cls=Parenthesis))
</span><span class="cx"> self.table.tableConstraint(Constraint.UNIQUE, names)
</span><del>- elif constraintType.match(Keyword, 'CHECK'):
</del><ins>+ elif constraintType.match(Keyword, "CHECK"):
</ins><span class="cx"> self.table.checkConstraint(self.readExpression(self.next()), ident)
</span><span class="cx"> else:
</span><del>- raise ViolatedExpectation('PRIMARY or UNIQUE', constraintType)
</del><ins>+ raise ViolatedExpectation("PRIMARY or UNIQUE", constraintType)
+
</ins><span class="cx"> return self.checkEnd(self.next())
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -375,9 +423,13 @@
</span><span class="cx"> [funcIdent, args] = iterSignificant(typeName)
</span><span class="cx"> typeName = funcIdent
</span><span class="cx"> arggetter = iterSignificant(args)
</span><del>- expect(arggetter, value=u'(')
- typeLength = int(expect(arggetter,
- ttype=Number.Integer).value.encode('utf-8'))
</del><ins>+ expect(arggetter, value=u"(")
+ typeLength = int(
+ expect(
+ arggetter,
+ ttype=Number.Integer
+ ).value.encode("utf-8")
+ )
</ins><span class="cx"> else:
</span><span class="cx"> maybeTypeArgs = self.next()
</span><span class="cx"> if isinstance(maybeTypeArgs, Parenthesis):
</span><span class="lines">@@ -389,98 +441,153 @@
</span><span class="cx"> # something else
</span><span class="cx"> typeLength = None
</span><span class="cx"> self.pushback(maybeTypeArgs)
</span><ins>+
</ins><span class="cx"> theType = SQLType(typeName.value.encode("utf-8"), typeLength)
</span><span class="cx"> theColumn = self.table.addColumn(
</span><span class="cx"> name=name.encode("utf-8"), type=theType
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> for val in self:
</span><span class="cx"> if val.ttype == Punctuation:
</span><span class="cx"> return self.checkEnd(val)
</span><span class="cx"> else:
</span><span class="cx"> expected = True
</span><ins>+
</ins><span class="cx"> def oneConstraint(t):
</span><span class="cx"> self.table.tableConstraint(t, [theColumn.name])
</span><span class="cx">
</span><del>- if val.match(Keyword, 'PRIMARY'):
- expect(self, ttype=Keyword, value='KEY')
</del><ins>+ if val.match(Keyword, "PRIMARY"):
+ expect(self, ttype=Keyword, value="KEY")
</ins><span class="cx"> # XXX check to make sure there's no other primary key yet
</span><span class="cx"> self.table.primaryKey = [theColumn]
</span><del>- elif val.match(Keyword, 'UNIQUE'):
</del><ins>+
+ elif val.match(Keyword, "UNIQUE"):
</ins><span class="cx"> # XXX add UNIQUE constraint
</span><span class="cx"> oneConstraint(Constraint.UNIQUE)
</span><del>- elif val.match(Keyword, 'NOT'):
- # possibly not necessary, as 'NOT NULL' is a single keyword
</del><ins>+
+ elif val.match(Keyword, "NOT"):
+ # possibly not necessary, as "NOT NULL" is a single keyword
</ins><span class="cx"> # in sqlparse as of 0.1.2
</span><del>- expect(self, ttype=Keyword, value='NULL')
</del><ins>+ expect(self, ttype=Keyword, value="NULL")
</ins><span class="cx"> oneConstraint(Constraint.NOT_NULL)
</span><del>- elif val.match(Keyword, 'NOT NULL'):
</del><ins>+
+ elif val.match(Keyword, "NOT NULL"):
</ins><span class="cx"> oneConstraint(Constraint.NOT_NULL)
</span><del>- elif val.match(Keyword, 'CHECK'):
- self.table.checkConstraint(self.readExpression(self.next()))
- elif val.match(Keyword, 'DEFAULT'):
</del><ins>+
+ elif val.match(Keyword, "CHECK"):
+ self.table.checkConstraint(
+ self.readExpression(self.next())
+ )
+
+ elif val.match(Keyword, "DEFAULT"):
</ins><span class="cx"> theDefault = self.next()
</span><ins>+
</ins><span class="cx"> if isinstance(theDefault, Parenthesis):
</span><span class="cx"> iDefault = iterSignificant(theDefault)
</span><span class="cx"> expect(iDefault, ttype=Punctuation, value="(")
</span><span class="cx"> theDefault = iDefault.next()
</span><ins>+
</ins><span class="cx"> if isinstance(theDefault, Function):
</span><span class="cx"> thingo = theDefault.tokens[0].get_name()
</span><span class="cx"> parens = expectSingle(
</span><span class="cx"> theDefault.tokens[-1], cls=Parenthesis
</span><span class="cx"> )
</span><span class="cx"> pareniter = iterSignificant(parens)
</span><del>- if thingo.upper() == 'NEXTVAL':
</del><ins>+ if thingo.upper() == "NEXTVAL":
</ins><span class="cx"> expect(pareniter, ttype=Punctuation, value="(")
</span><span class="cx"> seqname = _destringify(
</span><del>- expect(pareniter, ttype=String.Single).value)
</del><ins>+ expect(pareniter, ttype=String.Single).value
+ )
</ins><span class="cx"> defaultValue = self.table.schema.sequenceNamed(
</span><span class="cx"> seqname
</span><span class="cx"> )
</span><span class="cx"> defaultValue.referringColumns.append(theColumn)
</span><span class="cx"> else:
</span><del>- defaultValue = ProcedureCall(thingo.encode('utf-8'),
- parens)
</del><ins>+ defaultValue = ProcedureCall(
+ thingo.encode("utf-8"), parens
+ )
+
</ins><span class="cx"> elif theDefault.ttype == Number.Integer:
</span><span class="cx"> defaultValue = int(theDefault.value)
</span><del>- elif (theDefault.ttype == Keyword and
- theDefault.value.lower() == 'false'):
</del><ins>+
+ elif (
+ theDefault.ttype == Keyword and
+ theDefault.value.lower() == "false"
+ ):
</ins><span class="cx"> defaultValue = False
</span><del>- elif (theDefault.ttype == Keyword and
- theDefault.value.lower() == 'true'):
</del><ins>+
+ elif (
+ theDefault.ttype == Keyword and
+ theDefault.value.lower() == "true"
+ ):
</ins><span class="cx"> defaultValue = True
</span><del>- elif (theDefault.ttype == Keyword and
- theDefault.value.lower() == 'null'):
</del><ins>+
+ elif (
+ theDefault.ttype == Keyword and
+ theDefault.value.lower() == "null"
+ ):
</ins><span class="cx"> defaultValue = None
</span><ins>+
</ins><span class="cx"> elif theDefault.ttype == String.Single:
</span><span class="cx"> defaultValue = _destringify(theDefault.value)
</span><ins>+
</ins><span class="cx"> else:
</span><span class="cx"> raise RuntimeError(
</span><del>- "not sure what to do: default %r" % (
- theDefault))
</del><ins>+ "not sure what to do: default %r"
+ % (theDefault,)
+ )
+
</ins><span class="cx"> theColumn.setDefaultValue(defaultValue)
</span><del>- elif val.match(Keyword, 'REFERENCES'):
</del><ins>+
+ elif val.match(Keyword, "REFERENCES"):
</ins><span class="cx"> target = nameOrIdentifier(self.next())
</span><span class="cx"> theColumn.doesReferenceName(target)
</span><del>- elif val.match(Keyword, 'ON'):
- expect(self, ttype=Keyword.DML, value='DELETE')
</del><ins>+
+ elif val.match(Keyword, "ON"):
+ expect(self, ttype=Keyword.DML, value="DELETE")
</ins><span class="cx"> refAction = self.next()
</span><del>- if refAction.ttype == Keyword and refAction.value.upper() == 'CASCADE':
- theColumn.deleteAction = 'cascade'
- elif refAction.ttype == Keyword and refAction.value.upper() == 'SET':
</del><ins>+
+ if (
+ refAction.ttype == Keyword and
+ refAction.value.upper() == "CASCADE"
+ ):
+ theColumn.deleteAction = "cascade"
+
+ elif (
+ refAction.ttype == Keyword and
+ refAction.value.upper() == "SET"
+ ):
</ins><span class="cx"> setAction = self.next()
</span><del>- if setAction.ttype == Keyword and setAction.value.upper() == 'NULL':
- theColumn.deleteAction = 'set null'
- elif setAction.ttype == Keyword and setAction.value.upper() == 'DEFAULT':
- theColumn.deleteAction = 'set default'
</del><ins>+
+ if (
+ setAction.ttype == Keyword and
+ setAction.value.upper() == "NULL"
+ ):
+ theColumn.deleteAction = "set null"
+
+ elif (
+ setAction.ttype == Keyword and
+ setAction.value.upper() == "DEFAULT"
+ ):
+ theColumn.deleteAction = "set default"
+
</ins><span class="cx"> else:
</span><del>- raise RuntimeError("Invalid on delete set %r" % (setAction.value,))
</del><ins>+ raise RuntimeError(
+ "Invalid on delete set %r"
+ % (setAction.value,)
+ )
+
</ins><span class="cx"> else:
</span><del>- raise RuntimeError("Invalid on delete %r" % (refAction.value,))
</del><ins>+ raise RuntimeError(
+ "Invalid on delete %r"
+ % (refAction.value,)
+ )
</ins><span class="cx">
</span><span class="cx"> else:
</span><span class="cx"> expected = False
</span><ins>+
</ins><span class="cx"> if not expected:
</span><del>- print('UNEXPECTED TOKEN:', repr(val), theColumn)
</del><ins>+ print("UNEXPECTED TOKEN:", repr(val), theColumn)
</ins><span class="cx"> print(self.parens)
</span><span class="cx"> import pprint
</span><span class="cx"> pprint.pprint(self.parens.tokens)
</span><span class="lines">@@ -534,14 +641,17 @@
</span><span class="cx"> """
</span><span class="cx"> if ttype is not None:
</span><span class="cx"> if nextval.ttype != ttype:
</span><del>- raise ViolatedExpectation(ttype, '%s:%r' % (nextval.ttype, nextval))
</del><ins>+ raise ViolatedExpectation(
+ ttype, "%s:%r" % (nextval.ttype, nextval)
+ )
</ins><span class="cx"> if value is not None:
</span><span class="cx"> if nextval.value.upper() != value.upper():
</span><span class="cx"> raise ViolatedExpectation(value, nextval.value)
</span><span class="cx"> if cls is not None:
</span><span class="cx"> if nextval.__class__ != cls:
</span><del>- raise ViolatedExpectation(cls, '%s:%r' %
- (nextval.__class__.__name__, nextval))
</del><ins>+ raise ViolatedExpectation(
+ cls, "%s:%r" % (nextval.__class__.__name__, nextval)
+ )
</ins><span class="cx"> return nextval
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -560,10 +670,10 @@
</span><span class="cx">
</span><span class="cx"> def significant(token):
</span><span class="cx"> """
</span><del>- Determine if the token is 'significant', i.e. that it is not a comment and
</del><ins>+ Determine if the token is "significant", i.e. that it is not a comment and
</ins><span class="cx"> not whitespace.
</span><span class="cx"> """
</span><del>- # comment has 'None' is_whitespace() result. intentional?
</del><ins>+ # comment has None is_whitespace() result. intentional?
</ins><span class="cx"> return (not isinstance(token, Comment) and not token.is_whitespace())
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterprisedalrecordpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/record.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/record.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/record.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -22,6 +22,13 @@
</span><span class="cx"> L{twext.enterprise.dal.syntax}.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+__all__ = [
+ "ReadOnly",
+ "NoSuchRecord",
+ "fromTable",
+ "Record",
+]
+
</ins><span class="cx"> from twisted.internet.defer import inlineCallbacks, returnValue
</span><span class="cx"> from twext.enterprise.dal.syntax import (
</span><span class="cx"> Select, Tuple, Constant, ColumnSyntax, Insert, Update, Delete
</span><span class="lines">@@ -29,6 +36,8 @@
</span><span class="cx"> from twext.enterprise.util import parseSQLTimestamp
</span><span class="cx"> # from twext.enterprise.dal.syntax import ExpressionSyntax
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class ReadOnly(AttributeError):
</span><span class="cx"> """
</span><span class="cx"> A caller attempted to set an attribute on a database-backed record, rather
</span><span class="lines">@@ -38,10 +47,11 @@
</span><span class="cx"> def __init__(self, className, attributeName):
</span><span class="cx"> self.className = className
</span><span class="cx"> self.attributeName = attributeName
</span><del>- super(ReadOnly, self).__init__("SQL-backed attribute '{0}.{1}' is "
- "read-only. Use '.update(...)' to "
- "modify attributes."
- .format(className, attributeName))
</del><ins>+ super(ReadOnly, self).__init__(
+ "SQL-backed attribute '{0}.{1}' is read-only. "
+ "Use '.update(...)' to modify attributes."
+ .format(className, attributeName)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -65,6 +75,7 @@
</span><span class="cx"> newbases = []
</span><span class="cx"> table = None
</span><span class="cx"> namer = None
</span><ins>+
</ins><span class="cx"> for base in bases:
</span><span class="cx"> if isinstance(base, fromTable):
</span><span class="cx"> if table is not None:
</span><span class="lines">@@ -83,6 +94,7 @@
</span><span class="cx"> if isinstance(base, _RecordMeta):
</span><span class="cx"> namer = base
</span><span class="cx"> newbases.append(base)
</span><ins>+
</ins><span class="cx"> if table is not None:
</span><span class="cx"> attrmap = {}
</span><span class="cx"> colmap = {}
</span><span class="lines">@@ -93,6 +105,7 @@
</span><span class="cx"> colmap[column] = attrname
</span><span class="cx"> ns.update(table=table, __attrmap__=attrmap, __colmap__=colmap)
</span><span class="cx"> ns.update(attrmap)
</span><ins>+
</ins><span class="cx"> return super(_RecordMeta, cls).__new__(cls, name, tuple(newbases), ns)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -135,6 +148,7 @@
</span><span class="cx"> __metaclass__ = _RecordMeta
</span><span class="cx">
</span><span class="cx"> transaction = None
</span><ins>+
</ins><span class="cx"> def __setattr__(self, name, value):
</span><span class="cx"> """
</span><span class="cx"> Once the transaction is initialized, this object is immutable. If you
</span><span class="lines">@@ -142,12 +156,15 @@
</span><span class="cx"> """
</span><span class="cx"> if self.transaction is not None:
</span><span class="cx"> raise ReadOnly(self.__class__.__name__, name)
</span><ins>+
</ins><span class="cx"> return super(Record, self).__setattr__(name, value)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- r = "<{0} record from table {1}".format(self.__class__.__name__,
- self.table.model.name)
</del><ins>+ r = (
+ "<{0} record from table {1}"
+ .format(self.__class__.__name__, self.table.model.name)
+ )
</ins><span class="cx"> for k in sorted(self.__attrmap__.keys()):
</span><span class="cx"> r += " {0}={1}".format(k, repr(getattr(self, k)))
</span><span class="cx"> r += ">"
</span><span class="lines">@@ -162,11 +179,13 @@
</span><span class="cx"> names).
</span><span class="cx"> """
</span><span class="cx"> words = columnName.lower().split("_")
</span><ins>+
</ins><span class="cx"> def cap(word):
</span><del>- if word.lower() == 'id':
</del><ins>+ if word.lower() == "id":
</ins><span class="cx"> return word.upper()
</span><span class="cx"> else:
</span><span class="cx"> return word.capitalize()
</span><ins>+
</ins><span class="cx"> return words[0] + "".join(map(cap, words[1:]))
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -184,15 +203,16 @@
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="cx"> def _primaryKeyComparison(cls, primaryKey):
</span><del>- return (cls._primaryKeyExpression() ==
- Tuple(map(Constant, primaryKey)))
</del><ins>+ return cls._primaryKeyExpression() == Tuple(map(Constant, primaryKey))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def load(cls, transaction, *primaryKey):
</span><del>- results = (yield cls.query(transaction,
- cls._primaryKeyComparison(primaryKey)))
</del><ins>+ results = yield cls.query(
+ transaction,
+ cls._primaryKeyComparison(primaryKey)
+ )
</ins><span class="cx"> if len(results) != 1:
</span><span class="cx"> raise NoSuchRecord()
</span><span class="cx"> else:
</span><span class="lines">@@ -207,7 +227,7 @@
</span><span class="cx">
</span><span class="cx"> Used like this::
</span><span class="cx">
</span><del>- MyRecord.create(transaction, column1=1, column2=u'two')
</del><ins>+ MyRecord.create(transaction, column1=1, column2=u"two")
</ins><span class="cx"> """
</span><span class="cx"> self = cls()
</span><span class="cx"> colmap = {}
</span><span class="lines">@@ -222,11 +242,14 @@
</span><span class="cx"> colmap[col] = k.pop(attr)
</span><span class="cx"> else:
</span><span class="cx"> if col.model.needsValue():
</span><del>- raise TypeError("required attribute " + repr(attr) +
- " not passed")
</del><ins>+ raise TypeError(
+ "required attribute {0!r} not passed"
+ .format(attr)
+ )
</ins><span class="cx"> else:
</span><span class="cx"> needsCols.append(col)
</span><span class="cx"> needsAttrs.append(attr)
</span><ins>+
</ins><span class="cx"> if k:
</span><span class="cx"> raise TypeError("received unknown attribute{0}: {1}".format(
</span><span class="cx"> "s" if len(k) > 1 else "", ", ".join(sorted(k))
</span><span class="lines">@@ -235,7 +258,9 @@
</span><span class="cx"> .on(transaction))
</span><span class="cx"> if needsCols:
</span><span class="cx"> self._attributesFromRow(zip(needsAttrs, result[0]))
</span><ins>+
</ins><span class="cx"> self.transaction = transaction
</span><ins>+
</ins><span class="cx"> returnValue(self)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -262,9 +287,10 @@
</span><span class="cx"> has been deleted, or fails with L{NoSuchRecord} if the underlying
</span><span class="cx"> row was already deleted.
</span><span class="cx"> """
</span><del>- return Delete(From=self.table,
- Where=self._primaryKeyComparison(self._primaryKeyValue())
- ).on(self.transaction, raiseOnZeroRowCount=NoSuchRecord)
</del><ins>+ return Delete(
+ From=self.table,
+ Where=self._primaryKeyComparison(self._primaryKeyValue())
+ ).on(self.transaction, raiseOnZeroRowCount=NoSuchRecord)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="lines">@@ -278,9 +304,12 @@
</span><span class="cx"> colmap = {}
</span><span class="cx"> for k, v in kw.iteritems():
</span><span class="cx"> colmap[self.__attrmap__[k]] = v
</span><del>- yield (Update(colmap,
- Where=self._primaryKeyComparison(self._primaryKeyValue()))
- .on(self.transaction))
</del><ins>+
+ yield Update(
+ colmap,
+ Where=self._primaryKeyComparison(self._primaryKeyValue())
+ ).on(self.transaction)
+
</ins><span class="cx"> self.__dict__.update(kw)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -295,9 +324,13 @@
</span><span class="cx"> @rtype: L{Deferred}
</span><span class="cx"> """
</span><span class="cx"> return cls._rowsFromQuery(
</span><del>- transaction, Delete(Where=cls._primaryKeyComparison(primaryKey),
- From=cls.table, Return=list(cls.table)),
- lambda : NoSuchRecord()
</del><ins>+ transaction,
+ Delete(
+ Where=cls._primaryKeyComparison(primaryKey),
+ From=cls.table,
+ Return=list(cls.table)
+ ),
+ lambda: NoSuchRecord()
</ins><span class="cx"> ).addCallback(lambda x: x[0])
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -326,9 +359,11 @@
</span><span class="cx"> kw.update(OrderBy=order, Ascending=ascending)
</span><span class="cx"> if group is not None:
</span><span class="cx"> kw.update(GroupBy=group)
</span><del>- return cls._rowsFromQuery(transaction, Select(list(cls.table),
- From=cls.table,
- Where=expr, **kw), None)
</del><ins>+ return cls._rowsFromQuery(
+ transaction,
+ Select(list(cls.table), From=cls.table, Where=expr, **kw),
+ None
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="lines">@@ -337,11 +372,15 @@
</span><span class="cx"> Load all rows from the table that corresponds to C{cls} and return
</span><span class="cx"> instances of C{cls} corresponding to all.
</span><span class="cx"> """
</span><del>- return cls._rowsFromQuery(transaction,
- Select(list(cls.table),
- From=cls.table,
- OrderBy=cls._primaryKeyExpression()),
- None)
</del><ins>+ return cls._rowsFromQuery(
+ transaction,
+ Select(
+ list(cls.table),
+ From=cls.table,
+ OrderBy=cls._primaryKeyExpression()
+ ),
+ None
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="lines">@@ -354,7 +393,7 @@
</span><span class="cx"> @param transaction: an L{IAsyncTransaction} to execute the query on.
</span><span class="cx">
</span><span class="cx"> @param qry: a L{_DMLStatement} (XXX: maybe _DMLStatement or some
</span><del>- interface that defines 'on' should be public?) whose results are
</del><ins>+ interface that defines "on" should be public?) whose results are
</ins><span class="cx"> the list of columns in C{self.table}.
</span><span class="cx">
</span><span class="cx"> @param rozrc: The C{raiseOnZeroRowCount} argument.
</span><span class="lines">@@ -371,11 +410,3 @@
</span><span class="cx"> self.transaction = transaction
</span><span class="cx"> selves.append(self)
</span><span class="cx"> returnValue(selves)
</span><del>-
-
-
-__all__ = [
- "ReadOnly",
- "fromTable",
- "NoSuchRecord",
-]
</del></span></pre></div>
<a id="twexttrunktwextenterprisedalsyntaxpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/syntax.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/syntax.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/syntax.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -19,6 +19,56 @@
</span><span class="cx"> Syntax wrappers and generators for SQL.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+__all__ = [
+ "DALError",
+ "QueryPlaceholder",
+ "FixedPlaceholder",
+ "NumericPlaceholder",
+ "defaultPlaceholder",
+ "QueryGenerator",
+ "TableMismatch",
+ "NotEnoughValues",
+ "Syntax",
+ "comparison",
+ "ExpressionSyntax",
+ "FunctionInvocation",
+ "Constant",
+ "NamedValue",
+ "Function",
+ "SchemaSyntax",
+ "SequenceSyntax",
+ "TableSyntax",
+ "TableAlias",
+ "Join",
+ "ColumnSyntax",
+ "ResultAliasSyntax",
+ "AliasReferenceSyntax",
+ "AliasedColumnSyntax",
+ "Comparison",
+ "NullComparison",
+ "CompoundComparison",
+ "ColumnComparison",
+ "Column",
+ "Tuple",
+ "SetExpression",
+ "Union",
+ "Intersect",
+ "Except",
+ "Select",
+ "Insert",
+ "Update",
+ "Delete",
+ "Lock",
+ "DatabaseLock",
+ "DatabaseUnlock",
+ "RollbackToSavepoint",
+ "ReleaseSavepoint",
+ "SavepointAction",
+ "NoOp",
+ "SQLFragment",
+ "Parameter",
+]
+
</ins><span class="cx"> from itertools import count, repeat
</span><span class="cx"> from functools import partial
</span><span class="cx"> from operator import eq, ne
</span><span class="lines">@@ -88,7 +138,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def placeholder(self):
</span><del>- return ':' + str(self._next())
</del><ins>+ return ":" + str(self._next())
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -96,7 +146,7 @@
</span><span class="cx"> """
</span><span class="cx"> Generate a default L{QueryPlaceholder}
</span><span class="cx"> """
</span><del>- return FixedPlaceholder('?')
</del><ins>+ return FixedPlaceholder("?")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -146,9 +196,9 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> _paramstyles = {
</span><del>- 'pyformat': partial(FixedPlaceholder, "%s"),
- 'numeric': NumericPlaceholder,
- 'qmark': defaultPlaceholder,
</del><ins>+ "pyformat": partial(FixedPlaceholder, "%s"),
+ "numeric": NumericPlaceholder,
+ "qmark": defaultPlaceholder,
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -162,7 +212,7 @@
</span><span class="cx"> """
</span><span class="cx"> A hook for subclasses to provide additional keyword arguments to the
</span><span class="cx"> C{bind} call when L{_Statement.on} is executed. Currently this is used
</span><del>- only for 'out' parameters to capture results when executing statements
</del><ins>+ only for "out" parameters to capture results when executing statements
</ins><span class="cx"> that do not normally have a result (L{Insert}, L{Delete}, L{Update}).
</span><span class="cx"> """
</span><span class="cx"> return {}
</span><span class="lines">@@ -170,24 +220,23 @@
</span><span class="cx">
</span><span class="cx"> def _extraResult(self, result, outvars, queryGenerator):
</span><span class="cx"> """
</span><del>- A hook for subclasses to manipulate the results of 'on', after they've
</del><ins>+ A hook for subclasses to manipulate the results of "on", after they've
</ins><span class="cx"> been retrieved by the database but before they've been given to
</span><span class="cx"> application code.
</span><span class="cx">
</span><del>- @param result: a L{Deferred} that will fire with the rows as returned by
- the database.
</del><ins>+ @param result: a L{Deferred} that will fire with the rows as returned
+ by the database.
</ins><span class="cx"> @type result: C{list} of rows, which are C{list}s or C{tuple}s.
</span><span class="cx">
</span><span class="cx"> @param outvars: a dictionary of extra variables returned by
</span><span class="cx"> C{self._extraVars}.
</span><span class="cx">
</span><del>- @param queryGenerator: information about the connection where the statement
- was executed.
</del><ins>+ @param queryGenerator: information about the connection where the
+ statement was executed.
</ins><span class="cx">
</span><span class="cx"> @type queryGenerator: L{QueryGenerator} (a subclass thereof)
</span><span class="cx">
</span><span class="cx"> @return: the result to be returned from L{_Statement.on}.
</span><del>-
</del><span class="cx"> @rtype: L{Deferred} firing result rows
</span><span class="cx"> """
</span><span class="cx"> return result
</span><span class="lines">@@ -210,12 +259,15 @@
</span><span class="cx"> @rtype: a L{Deferred} firing a C{list} of records (C{tuple}s or
</span><span class="cx"> C{list}s)
</span><span class="cx"> """
</span><del>- queryGenerator = QueryGenerator(txn.dialect, self._paramstyles[txn.paramstyle]())
</del><ins>+ queryGenerator = QueryGenerator(
+ txn.dialect, self._paramstyles[txn.paramstyle]()
+ )
</ins><span class="cx"> outvars = self._extraVars(txn, queryGenerator)
</span><span class="cx"> kw.update(outvars)
</span><span class="cx"> fragment = self.toSQL(queryGenerator).bind(**kw)
</span><del>- result = txn.execSQL(fragment.text, fragment.parameters,
- raiseOnZeroRowCount)
</del><ins>+ result = txn.execSQL(
+ fragment.text, fragment.parameters, raiseOnZeroRowCount
+ )
</ins><span class="cx"> result = self._extraResult(result, outvars, queryGenerator)
</span><span class="cx"> if queryGenerator.dialect == ORACLE_DIALECT and result:
</span><span class="cx"> result.addCallback(self._fixOracleNulls)
</span><span class="lines">@@ -225,8 +277,9 @@
</span><span class="cx"> def _resultColumns(self):
</span><span class="cx"> """
</span><span class="cx"> Subclasses must implement this to return a description of the columns
</span><del>- expected to be returned. This is a list of L{ColumnSyntax} objects, and
- possibly other expression syntaxes which will be converted to C{None}.
</del><ins>+ expected to be returned. This is a list of L{ColumnSyntax} objects,
+ and possibly other expression syntaxes which will be converted to
+ C{None}.
</ins><span class="cx"> """
</span><span class="cx"> raise NotImplementedError(
</span><span class="cx"> "Each statement subclass must describe its result"
</span><span class="lines">@@ -253,19 +306,25 @@
</span><span class="cx"> """
</span><span class="cx"> if rows is None:
</span><span class="cx"> return None
</span><ins>+
</ins><span class="cx"> newRows = []
</span><ins>+
</ins><span class="cx"> for row in rows:
</span><span class="cx"> newRow = []
</span><ins>+
</ins><span class="cx"> for column, description in zip(row, self._resultShape()):
</span><del>- if ((description is not None and
- # FIXME: "is the python type str" is what I mean; this list
- # should be more centrally maintained
- description.type.name in ('varchar', 'text', 'char') and
- column is None
- )):
- column = ''
</del><ins>+ if (
+ description is not None and
+ # FIXME: "is the python type str" is what I mean; this list
+ # should be more centrally maintained
+ description.type.name in ("varchar", "text", "char") and
+ column is None
+ ):
+ column = ""
</ins><span class="cx"> newRow.append(column)
</span><ins>+
</ins><span class="cx"> newRows.append(newRow)
</span><ins>+
</ins><span class="cx"> return newRows
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -277,7 +336,7 @@
</span><span class="cx"> This class will define dynamic attribute access to represent its underlying
</span><span class="cx"> model as a Python namespace.
</span><span class="cx">
</span><del>- You can access the underlying model as '.model'.
</del><ins>+ You can access the underlying model as ".model".
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> modelType = None
</span><span class="lines">@@ -292,7 +351,7 @@
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><span class="cx"> if self.model is not None:
</span><del>- return '<Syntax for: %r>' % (self.model,)
</del><ins>+ return "<Syntax for: %r>" % (self.model,)
</ins><span class="cx"> return super(Syntax, self).__repr__()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -314,20 +373,20 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class ExpressionSyntax(Syntax):
</span><del>- __eq__ = comparison('=')
- __ne__ = comparison('!=')
</del><ins>+ __eq__ = comparison("=")
+ __ne__ = comparison("!=")
</ins><span class="cx">
</span><span class="cx"> # NB: these operators "cannot be used with lists" (see ORA-01796)
</span><del>- __gt__ = comparison('>')
- __ge__ = comparison('>=')
- __lt__ = comparison('<')
- __le__ = comparison('<=')
</del><ins>+ __gt__ = comparison(">")
+ __ge__ = comparison(">=")
+ __lt__ = comparison("<")
+ __le__ = comparison("<=")
</ins><span class="cx">
</span><span class="cx"> # TODO: operators aren't really comparisons; these should behave slightly
</span><del>- # differently. (For example; in Oracle, 'select 3 = 4 from dual' doesn't
- # work, but 'select 3 + 4 from dual' does; similarly, you can't do 'select *
- # from foo where 3 + 4', but you can do 'select * from foo where 3 + 4 >
- # 0'.)
</del><ins>+ # differently. (For example; in Oracle, C{select 3 = 4 from dual} doesn't
+ # work, but C{select 3 + 4 from dual} does; similarly, you can't do
+ # C{select * from foo where 3 + 4}, but you can do C{select * from foo
+ # where 3 + 4 > 0}.)
</ins><span class="cx"> __add__ = comparison("+")
</span><span class="cx"> __sub__ = comparison("-")
</span><span class="cx"> __div__ = comparison("/")
</span><span class="lines">@@ -341,32 +400,47 @@
</span><span class="cx">
</span><span class="cx"> def In(self, other):
</span><span class="cx"> """
</span><del>- We support two forms of the SQL "IN" syntax: one where a list of values is supplied, the other where
- a sub-select is used to provide a set of values.
</del><ins>+ We support two forms of the SQL "IN" syntax: one where a list of values
+ is supplied, the other where a sub-select is used to provide a set of
+ values.
</ins><span class="cx">
</span><span class="cx"> @param other: a constant parameter or sub-select
</span><span class="cx"> @type other: L{Parameter} or L{Select}
</span><span class="cx"> """
</span><span class="cx"> if isinstance(other, Parameter):
</span><span class="cx"> if other.count is None:
</span><del>- raise DALError("IN expression needs an explicit count of parameters")
- return CompoundComparison(self, 'in', Constant(other))
</del><ins>+ raise DALError(
+ "IN expression needs an explicit count of parameters"
+ )
+ return CompoundComparison(self, "in", Constant(other))
</ins><span class="cx"> else:
</span><del>- # Can't be Select.__contains__ because __contains__ gets __nonzero__
- # called on its result by the 'in' syntax.
- return CompoundComparison(self, 'in', other)
</del><ins>+ # Can't be Select.__contains__ because __contains__ gets
+ # __nonzero__ called on its result by the "in" syntax.
+ return CompoundComparison(self, "in", other)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def StartsWith(self, other):
</span><del>- return CompoundComparison(self, "like", CompoundComparison(Constant(other), '||', Constant('%')))
</del><ins>+ return CompoundComparison(
+ self, "like",
+ CompoundComparison(Constant(other), "||", Constant("%"))
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def EndsWith(self, other):
</span><del>- return CompoundComparison(self, "like", CompoundComparison(Constant('%'), '||', Constant(other)))
</del><ins>+ return CompoundComparison(
+ self, "like",
+ CompoundComparison(Constant("%"), "||", Constant(other))
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def Contains(self, other):
</span><del>- return CompoundComparison(self, "like", CompoundComparison(Constant('%'), '||', CompoundComparison(Constant(other), '||', Constant('%'))))
</del><ins>+ return CompoundComparison(
+ self, "like",
+ CompoundComparison(
+ Constant("%"), "||",
+ CompoundComparison(Constant(other), "||", Constant("%"))
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -390,16 +464,20 @@
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="cx"> result = SQLFragment(self.function.nameFor(queryGenerator))
</span><span class="cx"> result.append(_inParens(
</span><del>- _commaJoined(_convert(arg).subSQL(queryGenerator, allTables)
- for arg in self.args)))
</del><ins>+ _commaJoined(
+ _convert(arg).subSQL(queryGenerator, allTables)
+ for arg in self.args
+ )
+ ))
</ins><span class="cx"> return result
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class Constant(ExpressionSyntax):
</span><span class="cx"> """
</span><del>- Generates an expression for a place holder where a value will be bound to the query. If the constant is a Parameter
- with count > 1 then a parenthesized, comma-separated list of place holders will be generated.
</del><ins>+ Generates an expression for a place holder where a value will be bound to
+ the query. If the constant is a Parameter with count > 1 then a
+ parenthesized, comma-separated list of place holders will be generated.
</ins><span class="cx"> """
</span><span class="cx"> def __init__(self, value):
</span><span class="cx"> self.value = value
</span><span class="lines">@@ -411,11 +489,19 @@
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="cx"> if isinstance(self.value, Parameter) and self.value.count is not None:
</span><del>- return _inParens(_CommaList(
- [SQLFragment(queryGenerator.placeholder.placeholder(), [self.value] if ctr == 0 else []) for ctr in range(self.value.count)]
- ).subSQL(queryGenerator, allTables))
</del><ins>+ return _inParens(
+ _CommaList([
+ SQLFragment(
+ queryGenerator.placeholder.placeholder(),
+ [self.value] if counter == 0 else []
+ )
+ for counter in range(self.value.count)
+ ]).subSQL(queryGenerator, allTables)
+ )
</ins><span class="cx"> else:
</span><del>- return SQLFragment(queryGenerator.placeholder.placeholder(), [self.value])
</del><ins>+ return SQLFragment(
+ queryGenerator.placeholder.placeholder(), [self.value]
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -444,8 +530,12 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def nameFor(self, queryGenerator):
</span><del>- if queryGenerator.dialect == ORACLE_DIALECT and self.oracleName is not None:
</del><ins>+ if (
+ queryGenerator.dialect == ORACLE_DIALECT and
+ self.oracleName is not None
+ ):
</ins><span class="cx"> return self.oracleName
</span><ins>+
</ins><span class="cx"> return self.name
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -486,7 +576,9 @@
</span><span class="cx"> try:
</span><span class="cx"> seqModel = self.model.sequenceNamed(attr)
</span><span class="cx"> except KeyError:
</span><del>- raise AttributeError("schema has no table or sequence %r" % (attr,))
</del><ins>+ raise AttributeError(
+ "schema has no table or sequence %r" % (attr,)
+ )
</ins><span class="cx"> else:
</span><span class="cx"> return SequenceSyntax(seqModel)
</span><span class="cx"> else:
</span><span class="lines">@@ -523,8 +615,8 @@
</span><span class="cx">
</span><span class="cx"> def _nameForDialect(name, dialect):
</span><span class="cx"> """
</span><del>- If the given name is being computed in the oracle dialect, truncate it to 30
- characters.
</del><ins>+ If the given name is being computed in the oracle dialect, truncate it to
+ 30 characters.
</ins><span class="cx"> """
</span><span class="cx"> if dialect == ORACLE_DIALECT:
</span><span class="cx"> name = name[:30]
</span><span class="lines">@@ -546,44 +638,46 @@
</span><span class="cx">
</span><span class="cx"> As in SQL, C{someTable.join(someTable)} is an error; you can't join a
</span><span class="cx"> table against itself. However, C{t = someTable.alias();
</span><del>- someTable.join(t)} is usable as a 'from' clause.
</del><ins>+ someTable.join(t)} is usable as a C{from} clause.
</ins><span class="cx"> """
</span><span class="cx"> return TableAlias(self.model)
</span><span class="cx">
</span><span class="cx">
</span><del>- def join(self, otherTableSyntax, on=None, type=''):
</del><ins>+ def join(self, otherTableSyntax, on=None, type=""):
</ins><span class="cx"> """
</span><span class="cx"> Create a L{Join}, representing a join between two tables.
</span><span class="cx"> """
</span><span class="cx"> if on is None:
</span><del>- type = 'cross'
</del><ins>+ type = "cross"
</ins><span class="cx"> return Join(self, type, otherTableSyntax, on)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="cx"> """
</span><span class="cx"> Generate the L{SQLFragment} for this table's identification; this is
</span><del>- for use in a 'from' clause.
</del><ins>+ for use in a C{from} clause.
</ins><span class="cx"> """
</span><span class="cx"> # XXX maybe there should be a specific method which is only invoked
</span><span class="cx"> # from the FROM clause, that only tables and joins would implement?
</span><del>- return SQLFragment(_nameForDialect(self.model.name, queryGenerator.dialect))
</del><ins>+ return SQLFragment(
+ _nameForDialect(self.model.name, queryGenerator.dialect)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __getattr__(self, attr):
</span><span class="cx"> """
</span><span class="cx"> Attributes named after columns on a L{TableSyntax} are returned by
</span><span class="cx"> accessing their names as attributes. For example, if there is a schema
</span><del>- syntax object created from SQL equivalent to 'create table foo (bar
- integer, baz integer)', 'schemaSyntax.foo.bar' and
- 'schemaSyntax.foo.baz'
</del><ins>+ syntax object created from SQL equivalent to C{create table foo (bar
+ integer, baz integer)}, C{schemaSyntax.foo.bar} and
+ C{schemaSyntax.foo.baz}
</ins><span class="cx"> """
</span><span class="cx"> try:
</span><span class="cx"> column = self.model.columnNamed(attr)
</span><span class="cx"> except KeyError:
</span><del>- raise AttributeError("table {0} has no column {1}".format(
- self.model.name, attr
- ))
</del><ins>+ raise AttributeError(
+ "table {0} has no column {1}".format(self.model.name, attr)
+ )
</ins><span class="cx"> else:
</span><span class="cx"> return ColumnSyntax(column)
</span><span class="cx">
</span><span class="lines">@@ -640,7 +734,7 @@
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="cx"> """
</span><del>- Return an L{SQLFragment} with a string of the form C{'mytable myalias'}
</del><ins>+ Return an L{SQLFragment} with a string of the form C{"mytable myalias"}
</ins><span class="cx"> suitable for use in a FROM clause.
</span><span class="cx"> """
</span><span class="cx"> result = super(TableAlias, self).subSQL(queryGenerator, allTables)
</span><span class="lines">@@ -659,9 +753,11 @@
</span><span class="cx"> which is only stable within the query which populated C{allTables}.
</span><span class="cx"> @rtype: C{str}
</span><span class="cx"> """
</span><del>- anum = [t for t in allTables
- if isinstance(t, TableAlias)].index(self) + 1
- return 'alias%d' % (anum,)
</del><ins>+ anum = [
+ t for t in allTables
+ if isinstance(t, TableAlias)
+ ].index(self) + 1
+ return "alias%d" % (anum,)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __getattr__(self, attr):
</span><span class="lines">@@ -671,7 +767,7 @@
</span><span class="cx">
</span><span class="cx"> class Join(object):
</span><span class="cx"> """
</span><del>- A DAL object representing an SQL 'join' statement.
</del><ins>+ A DAL object representing an SQL C{join} statement.
</ins><span class="cx">
</span><span class="cx"> @ivar leftSide: a L{Join} or L{TableSyntax} representing the left side of
</span><span class="cx"> this join.
</span><span class="lines">@@ -679,11 +775,10 @@
</span><span class="cx"> @ivar rightSide: a L{TableSyntax} representing the right side of this join.
</span><span class="cx">
</span><span class="cx"> @ivar type: the type of join this is. For example, for a left outer join,
</span><del>- this would be C{'left outer'}.
</del><ins>+ this would be C{"left outer"}.
</ins><span class="cx"> @type type: C{str}
</span><span class="cx">
</span><del>- @ivar on: the 'on' clause of this table.
-
</del><ins>+ @ivar on: the "on" clause of this table.
</ins><span class="cx"> @type on: L{ExpressionSyntax}
</span><span class="cx"> """
</span><span class="cx">
</span><span class="lines">@@ -697,14 +792,14 @@
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="cx"> stmt = SQLFragment()
</span><span class="cx"> stmt.append(self.leftSide.subSQL(queryGenerator, allTables))
</span><del>- stmt.text += ' '
</del><ins>+ stmt.text += " "
</ins><span class="cx"> if self.type:
</span><span class="cx"> stmt.text += self.type
</span><del>- stmt.text += ' '
- stmt.text += 'join '
</del><ins>+ stmt.text += " "
+ stmt.text += "join "
</ins><span class="cx"> stmt.append(self.rightSide.subSQL(queryGenerator, allTables))
</span><del>- if self.type != 'cross':
- stmt.text += ' on '
</del><ins>+ if self.type != "cross":
+ stmt.text += " on "
</ins><span class="cx"> stmt.append(self.on.subSQL(queryGenerator, allTables))
</span><span class="cx"> return stmt
</span><span class="cx">
</span><span class="lines">@@ -720,22 +815,25 @@
</span><span class="cx">
</span><span class="cx"> def join(self, otherTable, on=None, type=None):
</span><span class="cx"> if on is None:
</span><del>- type = 'cross'
</del><ins>+ type = "cross"
</ins><span class="cx"> return Join(self, type, otherTable, on)
</span><span class="cx">
</span><span class="cx">
</span><del>-_KEYWORDS = ["access",
- # SQL keyword, but we have a column with this name
- "path",
- # Not actually a standard keyword, but a function in oracle, and we
- # have a column with this name.
- "size",
- # not actually sure what this is; only experimentally determined
- # that not quoting it causes an issue.
- ]
</del><ins>+_KEYWORDS = [
+ # SQL keyword, but we have a column with this name
+ "access",
</ins><span class="cx">
</span><ins>+ # Not actually a standard keyword, but a function in oracle, and we have a
+ # column with this name.
+ "path",
</ins><span class="cx">
</span><ins>+ # not actually sure what this is; only experimentally determined that not
+ # quoting it causes an issue.
+ "size",
+]
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class ColumnSyntax(ExpressionSyntax):
</span><span class="cx"> """
</span><span class="cx"> Syntactic convenience for L{Column}.
</span><span class="lines">@@ -756,7 +854,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><del>- # XXX This, and 'model', could in principle conflict with column names.
</del><ins>+ # XXX This, and "model", could in principle conflict with column names.
</ins><span class="cx"> # Maybe do something about that.
</span><span class="cx"> name = self.model.name
</span><span class="cx"> if queryGenerator.shouldQuote(name):
</span><span class="lines">@@ -768,8 +866,12 @@
</span><span class="cx"> qualified = False
</span><span class="cx"> for tableSyntax in allTables:
</span><span class="cx"> if self.model.table is not tableSyntax.model:
</span><del>- if self.model.name in (c.name for c in
- tableSyntax.model.columns):
</del><ins>+ if (
+ self.model.name in (
+ c.name for c in
+ tableSyntax.model.columns
+ )
+ ):
</ins><span class="cx"> qualified = True
</span><span class="cx"> break
</span><span class="cx"> if qualified:
</span><span class="lines">@@ -783,7 +885,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _qualify(self, name, allTables):
</span><del>- return self.model.table.name + '.' + name
</del><ins>+ return self.model.table.name + "." + name
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -835,8 +937,8 @@
</span><span class="cx"> """
</span><span class="cx"> An L{AliasedColumnSyntax} is like a L{ColumnSyntax}, but it generates SQL
</span><span class="cx"> for a column of a table under an alias, rather than directly. i.e. this is
</span><del>- used for C{'something.col'} in C{'select something.col from tablename
- something'} rather than the 'col' in C{'select col from tablename'}.
</del><ins>+ used for C{"something.col"} in C{"select something.col from tablename
+ something"} rather than the "col" in C{"select col from tablename"}.
</ins><span class="cx">
</span><span class="cx"> @see: L{TableSyntax.alias}
</span><span class="cx"> """
</span><span class="lines">@@ -850,7 +952,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _qualify(self, name, allTables):
</span><del>- return self._tableAlias._aliasName(allTables) + '.' + name
</del><ins>+ return self._tableAlias._aliasName(allTables) + "." + name
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -864,7 +966,7 @@
</span><span class="cx">
</span><span class="cx"> def _subexpression(self, expr, queryGenerator, allTables):
</span><span class="cx"> result = expr.subSQL(queryGenerator, allTables)
</span><del>- if self.op not in ('and', 'or') and isinstance(expr, Comparison):
</del><ins>+ if self.op not in ("and", "or") and isinstance(expr, Comparison):
</ins><span class="cx"> result = _inParens(result)
</span><span class="cx"> return result
</span><span class="cx">
</span><span class="lines">@@ -874,11 +976,11 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def And(self, other):
</span><del>- return self.booleanOp('and', other)
</del><ins>+ return self.booleanOp("and", other)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def Or(self, other):
</span><del>- return self.booleanOp('or', other)
</del><ins>+ return self.booleanOp("or", other)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -887,7 +989,7 @@
</span><span class="cx"> A L{NullComparison} is a comparison of a column or expression with None.
</span><span class="cx"> """
</span><span class="cx"> def __init__(self, a, op):
</span><del>- # 'b' is always None for this comparison type
</del><ins>+ # "b" is always None for this comparison type
</ins><span class="cx"> super(NullComparison, self).__init__(a, op, None)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -913,36 +1015,50 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><del>- if (queryGenerator.dialect == ORACLE_DIALECT
- and isinstance(self.b, Constant) and self.b.value == ''
- and self.op in ('=', '!=')):
- return NullComparison(self.a, self.op).subSQL(queryGenerator, allTables)
</del><ins>+ if (
+ queryGenerator.dialect == ORACLE_DIALECT and
+ isinstance(self.b, Constant) and
+ self.b.value == "" and self.op in ("=", "!=")
+ ):
+ return NullComparison(self.a, self.op).subSQL(
+ queryGenerator, allTables
+ )
+
</ins><span class="cx"> stmt = SQLFragment()
</span><span class="cx"> result = self._subexpression(self.a, queryGenerator, allTables)
</span><del>- if (isinstance(self.a, CompoundComparison)
- and self.a.op == 'or' and self.op == 'and'):
</del><ins>+ if (
+ isinstance(self.a, CompoundComparison) and
+ self.a.op == "or" and self.op == "and"
+ ):
</ins><span class="cx"> result = _inParens(result)
</span><span class="cx"> stmt.append(result)
</span><span class="cx">
</span><del>- stmt.text += ' %s ' % (self.op,)
</del><ins>+ stmt.text += " %s " % (self.op,)
</ins><span class="cx">
</span><span class="cx"> result = self._subexpression(self.b, queryGenerator, allTables)
</span><del>- if (isinstance(self.b, CompoundComparison)
- and self.b.op == 'or' and self.op == 'and'):
</del><ins>+ if (
+ isinstance(self.b, CompoundComparison) and
+ self.b.op == "or" and self.op == "and"
+ ):
</ins><span class="cx"> result = _inParens(result)
</span><ins>+
</ins><span class="cx"> if isinstance(self.b, Tuple):
</span><span class="cx"> # If the right-hand side of the comparison is a Tuple, it needs to
</span><span class="cx"> # be double-parenthesized in Oracle, as per
</span><span class="cx"> # http://docs.oracle.com/cd/B28359_01/server.111/b28286/expressions015.htm#i1033664
</span><span class="cx"> # because it is an expression list.
</span><span class="cx"> result = _inParens(result)
</span><ins>+
</ins><span class="cx"> stmt.append(result)
</span><ins>+
</ins><span class="cx"> return stmt
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> _operators = {"=": eq, "!=": ne}
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class ColumnComparison(CompoundComparison):
</span><span class="cx"> """
</span><span class="cx"> Comparing two columns is the same as comparing any other two expressions,
</span><span class="lines">@@ -967,6 +1083,7 @@
</span><span class="cx"> def allColumns(self):
</span><span class="cx"> return []
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> ALL_COLUMNS = _AllColumns()
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1014,9 +1131,9 @@
</span><span class="cx"> if column in table:
</span><span class="cx"> break
</span><span class="cx"> else:
</span><del>- raise TableMismatch("{} not found in {}".format(
- column, tables
- ))
</del><ins>+ raise TableMismatch(
+ "{} not found in {}".format(column, tables)
+ )
</ins><span class="cx"> return None
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1032,8 +1149,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><del>- return _inParens(_commaJoined(c.subSQL(queryGenerator, allTables)
- for c in self.columns))
</del><ins>+ return _inParens(_commaJoined(
+ c.subSQL(queryGenerator, allTables)
+ for c in self.columns
+ ))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def allColumns(self):
</span><span class="lines">@@ -1051,10 +1170,11 @@
</span><span class="cx">
</span><span class="cx"> def __init__(self, selects, optype=None):
</span><span class="cx"> """
</span><del>-
</del><span class="cx"> @param selects: a single Select or a list of Selects
</span><span class="cx"> @type selects: C{list} or L{Select}
</span><del>- @param optype: whether to use the ALL, DISTINCT constructs: C{None} use neither, OPTYPE_ALL, or OPTYPE_DISTINCT
</del><ins>+
+ @param optype: whether to use the ALL, DISTINCT constructs: C{None} use
+ neither, OPTYPE_ALL, or OPTYPE_DISTINCT
</ins><span class="cx"> @type optype: C{str}
</span><span class="cx"> """
</span><span class="cx">
</span><span class="lines">@@ -1065,9 +1185,15 @@
</span><span class="cx">
</span><span class="cx"> for select in self.selects:
</span><span class="cx"> if not isinstance(select, Select):
</span><del>- raise DALError("Must have SELECT statements in a set expression")
- if self.optype not in (None, SetExpression.OPTYPE_ALL, SetExpression.OPTYPE_DISTINCT,):
- raise DALError("Must have either 'all' or 'distinct' in a set expression")
</del><ins>+ raise DALError(
+ "Must have SELECT statements in a set expression"
+ )
+ if self.optype not in (
+ None, SetExpression.OPTYPE_ALL, SetExpression.OPTYPE_DISTINCT,
+ ):
+ raise DALError(
+ "Must have either 'all' or 'distinct' in a set expression"
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><span class="lines">@@ -1121,13 +1247,16 @@
</span><span class="cx">
</span><span class="cx"> class Select(_Statement):
</span><span class="cx"> """
</span><del>- 'select' statement.
</del><ins>+ C{select} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><del>- def __init__(self, columns=None, Where=None, From=None, OrderBy=None,
- GroupBy=None, Limit=None, ForUpdate=False, NoWait=False, Ascending=None,
- Having=None, Distinct=False, As=None,
- SetExpression=None):
</del><ins>+ def __init__(
+ self,
+ columns=None, Where=None, From=None,
+ OrderBy=None, GroupBy=None,
+ Limit=None, ForUpdate=False, NoWait=False, Ascending=None,
+ Having=None, Distinct=False, As=None, SetExpression=None
+ ):
</ins><span class="cx"> self.From = From
</span><span class="cx"> self.Where = Where
</span><span class="cx"> self.Distinct = Distinct
</span><span class="lines">@@ -1165,30 +1294,33 @@
</span><span class="cx"> """
</span><span class="cx"> if isinstance(other, (list, tuple)):
</span><span class="cx"> other = Tuple(other)
</span><del>- return CompoundComparison(other, '=', self)
</del><ins>+ return CompoundComparison(other, "=", self)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> """
</span><del>- @return: a 'select' statement with placeholders and arguments
-
</del><ins>+ @return: a C{select} statement with placeholders and arguments
</ins><span class="cx"> @rtype: L{SQLFragment}
</span><span class="cx"> """
</span><span class="cx"> if self.SetExpression is not None:
</span><span class="cx"> stmt = SQLFragment("(")
</span><span class="cx"> else:
</span><span class="cx"> stmt = SQLFragment()
</span><ins>+
</ins><span class="cx"> stmt.append(SQLFragment("select "))
</span><span class="cx"> if self.Distinct:
</span><span class="cx"> stmt.text += "distinct "
</span><ins>+
</ins><span class="cx"> allTables = self.From.tables()
</span><span class="cx"> stmt.append(self.columns.subSQL(queryGenerator, allTables))
</span><span class="cx"> stmt.text += " from "
</span><span class="cx"> stmt.append(self.From.subSQL(queryGenerator, allTables))
</span><ins>+
</ins><span class="cx"> if self.Where is not None:
</span><span class="cx"> wherestmt = self.Where.subSQL(queryGenerator, allTables)
</span><span class="cx"> stmt.text += " where "
</span><span class="cx"> stmt.append(wherestmt)
</span><ins>+
</ins><span class="cx"> if self.GroupBy is not None:
</span><span class="cx"> stmt.text += " group by "
</span><span class="cx"> fst = True
</span><span class="lines">@@ -1196,15 +1328,18 @@
</span><span class="cx"> if fst:
</span><span class="cx"> fst = False
</span><span class="cx"> else:
</span><del>- stmt.text += ', '
</del><ins>+ stmt.text += ", "
</ins><span class="cx"> stmt.append(subthing.subSQL(queryGenerator, allTables))
</span><ins>+
</ins><span class="cx"> if self.Having is not None:
</span><span class="cx"> havingstmt = self.Having.subSQL(queryGenerator, allTables)
</span><span class="cx"> stmt.text += " having "
</span><span class="cx"> stmt.append(havingstmt)
</span><ins>+
</ins><span class="cx"> if self.SetExpression is not None:
</span><span class="cx"> stmt.append(SQLFragment(")"))
</span><span class="cx"> stmt.append(self.SetExpression.subSQL(queryGenerator, allTables))
</span><ins>+
</ins><span class="cx"> if self.OrderBy is not None:
</span><span class="cx"> stmt.text += " order by "
</span><span class="cx"> fst = True
</span><span class="lines">@@ -1212,7 +1347,7 @@
</span><span class="cx"> if fst:
</span><span class="cx"> fst = False
</span><span class="cx"> else:
</span><del>- stmt.text += ', '
</del><ins>+ stmt.text += ", "
</ins><span class="cx"> stmt.append(subthing.subSQL(queryGenerator, allTables))
</span><span class="cx"> if self.Ascending is not None:
</span><span class="cx"> if self.Ascending:
</span><span class="lines">@@ -1220,10 +1355,12 @@
</span><span class="cx"> else:
</span><span class="cx"> kw = " desc"
</span><span class="cx"> stmt.append(SQLFragment(kw))
</span><ins>+
</ins><span class="cx"> if self.ForUpdate:
</span><span class="cx"> stmt.text += " for update"
</span><span class="cx"> if self.NoWait:
</span><span class="cx"> stmt.text += " nowait"
</span><ins>+
</ins><span class="cx"> if self.Limit is not None:
</span><span class="cx"> limitConst = Constant(self.Limit).subSQL(queryGenerator, allTables)
</span><span class="cx"> if queryGenerator.dialect == ORACLE_DIALECT:
</span><span class="lines">@@ -1234,6 +1371,7 @@
</span><span class="cx"> else:
</span><span class="cx"> stmt.text += " limit "
</span><span class="cx"> stmt.append(limitConst)
</span><ins>+
</ins><span class="cx"> return stmt
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1241,10 +1379,12 @@
</span><span class="cx"> result = SQLFragment("(")
</span><span class="cx"> result.append(self.toSQL(queryGenerator))
</span><span class="cx"> result.append(SQLFragment(")"))
</span><ins>+
</ins><span class="cx"> if self.As is not None:
</span><span class="cx"> if self.As == "":
</span><span class="cx"> self.As = queryGenerator.nextGeneratedID()
</span><span class="cx"> result.append(SQLFragment(" %s" % (self.As,)))
</span><ins>+
</ins><span class="cx"> return result
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1278,7 +1418,10 @@
</span><span class="cx"> # the right rows.
</span><span class="cx"> return self.From.tables()
</span><span class="cx"> else:
</span><del>- tables = set([column.model.table for column in self.columns.columns if isinstance(column, ColumnSyntax)])
</del><ins>+ tables = set([
+ column.model.table for column in self.columns.columns
+ if isinstance(column, ColumnSyntax)
+ ])
</ins><span class="cx"> for table in self.From.tables():
</span><span class="cx"> tables.add(table.model)
</span><span class="cx"> return [TableSyntax(table) for table in tables]
</span><span class="lines">@@ -1333,8 +1476,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def subSQL(self, queryGenerator, allTables):
</span><del>- return _commaJoined(f.subSQL(queryGenerator, allTables)
- for f in self.subfragments)
</del><ins>+ return _commaJoined(
+ f.subSQL(queryGenerator, allTables)
+ for f in self.subfragments
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1345,14 +1490,14 @@
</span><span class="cx">
</span><span class="cx"> def _returningClause(self, queryGenerator, stmt, allTables):
</span><span class="cx"> """
</span><del>- Add a dialect-appropriate 'returning' clause to the end of the given
</del><ins>+ Add a dialect-appropriate C{returning} clause to the end of the given
</ins><span class="cx"> SQL statement.
</span><span class="cx">
</span><span class="cx"> @param queryGenerator: describes the database we are generating the
</span><span class="cx"> statement for.
</span><span class="cx"> @type queryGenerator: L{QueryGenerator}
</span><span class="cx">
</span><del>- @param stmt: the SQL fragment generated without the 'returning' clause
</del><ins>+ @param stmt: the SQL fragment generated without the C{returning} clause
</ins><span class="cx"> @type stmt: L{SQLFragment}
</span><span class="cx">
</span><span class="cx"> @param allTables: all tables involved in the query; see any C{subSQL}
</span><span class="lines">@@ -1361,18 +1506,22 @@
</span><span class="cx"> @return: the C{stmt} parameter.
</span><span class="cx"> """
</span><span class="cx"> retclause = self.Return
</span><ins>+
</ins><span class="cx"> if retclause is None:
</span><span class="cx"> return stmt
</span><ins>+
</ins><span class="cx"> if isinstance(retclause, (tuple, list)):
</span><span class="cx"> retclause = _CommaList(retclause)
</span><ins>+
</ins><span class="cx"> if queryGenerator.dialect == SQLITE_DIALECT:
</span><span class="cx"> # sqlite does this another way.
</span><span class="cx"> return stmt
</span><del>- elif retclause is not None:
- stmt.text += ' returning '
</del><ins>+
+ if retclause is not None:
+ stmt.text += " returning "
</ins><span class="cx"> stmt.append(retclause.subSQL(queryGenerator, allTables))
</span><span class="cx"> if queryGenerator.dialect == ORACLE_DIALECT:
</span><del>- stmt.text += ' into '
</del><ins>+ stmt.text += " into "
</ins><span class="cx"> params = []
</span><span class="cx"> retvals = self._returnAsList()
</span><span class="cx"> for n, _ignore_v in enumerate(retvals):
</span><span class="lines">@@ -1381,6 +1530,7 @@
</span><span class="cx"> .subSQL(queryGenerator, allTables)
</span><span class="cx"> )
</span><span class="cx"> stmt.append(_commaJoined(params))
</span><ins>+
</ins><span class="cx"> return stmt
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1403,7 +1553,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _extraResult(self, result, outvars, queryGenerator):
</span><del>- if queryGenerator.dialect == ORACLE_DIALECT and self.Return is not None:
</del><ins>+ if (
+ queryGenerator.dialect == ORACLE_DIALECT and
+ self.Return is not None
+ ):
</ins><span class="cx"> def processIt(shouldBeNone):
</span><span class="cx"> result = [[v.value for _ignore_k, v in outvars]]
</span><span class="cx"> return result
</span><span class="lines">@@ -1429,10 +1582,10 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def preQuery(self, cursor):
</span><del>- typeMap = {'integer': cx_Oracle.NUMBER,
- 'text': cx_Oracle.NCLOB,
- 'varchar': cx_Oracle.STRING,
- 'timestamp': cx_Oracle.TIMESTAMP}
</del><ins>+ typeMap = {"integer": cx_Oracle.NUMBER,
+ "text": cx_Oracle.NCLOB,
+ "varchar": cx_Oracle.STRING,
+ "timestamp": cx_Oracle.TIMESTAMP}
</ins><span class="cx"> self.var = cursor.var(typeMap[self.typeID])
</span><span class="cx"> return self.var
</span><span class="cx">
</span><span class="lines">@@ -1445,7 +1598,7 @@
</span><span class="cx">
</span><span class="cx"> class Insert(_DMLStatement):
</span><span class="cx"> """
</span><del>- 'insert' statement.
</del><ins>+ C{insert} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, columnMap, Return=None):
</span><span class="lines">@@ -1458,19 +1611,21 @@
</span><span class="cx"> if column not in columns]
</span><span class="cx"> if unspecified:
</span><span class="cx"> raise NotEnoughValues(
</span><del>- 'Columns [%s] required.' %
- (', '.join([c.name for c in unspecified])))
</del><ins>+ "Columns [%s] required."
+ % (", ".join([c.name for c in unspecified]))
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> """
</span><del>- @return: a 'insert' statement with placeholders and arguments
</del><ins>+ @return: a C{insert} statement with placeholders and arguments
</ins><span class="cx">
</span><span class="cx"> @rtype: L{SQLFragment}
</span><span class="cx"> """
</span><span class="cx"> columnsAndValues = self.columnMap.items()
</span><span class="cx"> tableModel = columnsAndValues[0][0].model.table
</span><span class="cx"> specifiedColumnModels = [x.model for x in self.columnMap.keys()]
</span><ins>+
</ins><span class="cx"> if queryGenerator.dialect == ORACLE_DIALECT:
</span><span class="cx"> # See test_nextSequenceDefaultImplicitExplicitOracle.
</span><span class="cx"> for column in tableModel.columns:
</span><span class="lines">@@ -1480,19 +1635,26 @@
</span><span class="cx"> columnsAndValues.append(
</span><span class="cx"> (columnSyntax, SequenceSyntax(column.default))
</span><span class="cx"> )
</span><del>- sortedColumns = sorted(columnsAndValues,
- key=lambda (c, v): c.model.name)
</del><ins>+
+ sortedColumns = sorted(
+ columnsAndValues,
+ key=lambda (c, v): c.model.name
+ )
</ins><span class="cx"> allTables = []
</span><del>- stmt = SQLFragment('insert into ')
</del><ins>+
+ stmt = SQLFragment("insert into ")
</ins><span class="cx"> stmt.append(TableSyntax(tableModel).subSQL(queryGenerator, allTables))
</span><span class="cx"> stmt.append(SQLFragment(" "))
</span><del>- stmt.append(_inParens(_commaJoined(
- [c.subSQL(queryGenerator, allTables) for (c, _ignore_v) in
- sortedColumns])))
</del><ins>+ stmt.append(_inParens(_commaJoined([
+ c.subSQL(queryGenerator, allTables)
+ for (c, _ignore_v) in sortedColumns
+ ])))
</ins><span class="cx"> stmt.append(SQLFragment(" values "))
</span><del>- stmt.append(_inParens(_commaJoined(
- [_convert(v).subSQL(queryGenerator, allTables)
- for (c, v) in sortedColumns])))
</del><ins>+ stmt.append(_inParens(_commaJoined([
+ _convert(v).subSQL(queryGenerator, allTables)
+ for (c, v) in sortedColumns
+ ])))
+
</ins><span class="cx"> return self._returningClause(queryGenerator, stmt, allTables)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1505,14 +1667,17 @@
</span><span class="cx"> result = super(_DMLStatement, self).on(txn, *a, **kw)
</span><span class="cx"> if self.Return is not None and txn.dialect == SQLITE_DIALECT:
</span><span class="cx"> table = self._returnAsList()[0].model.table
</span><del>- return Select(self._returnAsList(),
- # TODO: error reporting when 'return' includes columns
- # foreign to the primary table.
- From=TableSyntax(table),
- Where=ColumnSyntax(Column(table, "rowid",
- SQLType("integer", None))) ==
- _sqliteLastInsertRowID()
- ).on(txn, *a, **kw)
</del><ins>+ return Select(
+ self._returnAsList(),
+ # TODO: error reporting when "return" includes columns
+ # foreign to the primary table.
+ From=TableSyntax(table),
+ Where=(
+ ColumnSyntax(
+ Column(table, "rowid", SQLType("integer", None))
+ ) == _sqliteLastInsertRowID()
+ )
+ ).on(txn, *a, **kw)
</ins><span class="cx"> return result
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1531,7 +1696,7 @@
</span><span class="cx">
</span><span class="cx"> class Update(_DMLStatement):
</span><span class="cx"> """
</span><del>- 'update' statement
</del><ins>+ C{update} statement
</ins><span class="cx">
</span><span class="cx"> @ivar columnMap: A L{dict} mapping L{ColumnSyntax} objects to values to
</span><span class="cx"> change; values may be simple database values (such as L{str},
</span><span class="lines">@@ -1567,13 +1732,16 @@
</span><span class="cx"> preresult = prequery.on(txn, *a, **kw)
</span><span class="cx"> before = yield preresult
</span><span class="cx"> yield upcall()
</span><del>- result = (yield Select(self._returnAsList(),
- # TODO: error reporting when 'return' includes
- # columns foreign to the primary table.
- From=TableSyntax(table),
- Where=reduce(lambda left, right: left.Or(right),
- ((rowidcol == x) for [x] in before))
- ).on(txn, *a, **kw))
</del><ins>+ result = yield Select(
+ self._returnAsList(),
+ # TODO: error reporting when "return" includes
+ # columns foreign to the primary table.
+ From=TableSyntax(table),
+ Where=reduce(
+ lambda left, right: left.Or(right),
+ ((rowidcol == x) for [x] in before)
+ )
+ ).on(txn, *a, **kw)
</ins><span class="cx"> returnValue(result)
</span><span class="cx"> else:
</span><span class="cx"> returnValue((yield upcall()))
</span><span class="lines">@@ -1581,37 +1749,40 @@
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> """
</span><del>- @return: a 'insert' statement with placeholders and arguments
-
</del><ins>+ @return: an C{insert} statement with placeholders and arguments
</ins><span class="cx"> @rtype: L{SQLFragment}
</span><span class="cx"> """
</span><del>- sortedColumns = sorted(self.columnMap.items(),
- key=lambda (c, v): c.model.name)
</del><ins>+ sortedColumns = sorted(
+ self.columnMap.items(), key=lambda (c, v): c.model.name
+ )
</ins><span class="cx"> allTables = []
</span><del>- result = SQLFragment('update ')
</del><ins>+ result = SQLFragment("update ")
</ins><span class="cx"> result.append(
</span><span class="cx"> TableSyntax(sortedColumns[0][0].model.table).subSQL(
</span><del>- queryGenerator, allTables)
</del><ins>+ queryGenerator, allTables
+ )
</ins><span class="cx"> )
</span><del>- result.text += ' set '
- result.append(
- _commaJoined(
- [c.subSQL(queryGenerator, allTables).append(
- SQLFragment(" = ").subSQL(queryGenerator, allTables)
- ).append(_convert(v).subSQL(queryGenerator, allTables))
- for (c, v) in sortedColumns]
</del><ins>+ result.text += " set "
+ result.append(_commaJoined([
+ c.subSQL(queryGenerator, allTables).append(
+ SQLFragment(" = ").subSQL(queryGenerator, allTables)
+ ).append(
+ _convert(v).subSQL(queryGenerator, allTables)
</ins><span class="cx"> )
</span><del>- )
</del><ins>+ for (c, v) in sortedColumns
+ ]))
+
</ins><span class="cx"> if self.Where is not None:
</span><del>- result.append(SQLFragment(' where '))
</del><ins>+ result.append(SQLFragment(" where "))
</ins><span class="cx"> result.append(self.Where.subSQL(queryGenerator, allTables))
</span><ins>+
</ins><span class="cx"> return self._returningClause(queryGenerator, result, allTables)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class Delete(_DMLStatement):
</span><span class="cx"> """
</span><del>- 'delete' statement.
</del><ins>+ C{delete} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, From, Where, Return=None):
</span><span class="lines">@@ -1626,10 +1797,10 @@
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> result = SQLFragment()
</span><span class="cx"> allTables = self.From.tables()
</span><del>- result.text += 'delete from '
</del><ins>+ result.text += "delete from "
</ins><span class="cx"> result.append(self.From.subSQL(queryGenerator, allTables))
</span><span class="cx"> if self.Where is not None:
</span><del>- result.text += ' where '
</del><ins>+ result.text += " where "
</ins><span class="cx"> result.append(self.Where.subSQL(queryGenerator, allTables))
</span><span class="cx"> return self._returningClause(queryGenerator, result, allTables)
</span><span class="cx">
</span><span class="lines">@@ -1638,8 +1809,10 @@
</span><span class="cx"> def on(self, txn, *a, **kw):
</span><span class="cx"> upcall = lambda: super(Delete, self).on(txn, *a, **kw)
</span><span class="cx"> if txn.dialect == SQLITE_DIALECT and self.Return is not None:
</span><del>- result = yield Select(self._returnAsList(), From=self.From,
- Where=self.Where).on(txn, *a, **kw)
</del><ins>+ result = yield Select(
+ self._returnAsList(),
+ From=self.From, Where=self.Where
+ ).on(txn, *a, **kw)
</ins><span class="cx"> yield upcall()
</span><span class="cx"> else:
</span><span class="cx"> result = yield upcall()
</span><span class="lines">@@ -1661,7 +1834,7 @@
</span><span class="cx">
</span><span class="cx"> class Lock(_LockingStatement):
</span><span class="cx"> """
</span><del>- An SQL 'lock' statement.
</del><ins>+ An SQL "lock" statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, table, mode):
</span><span class="lines">@@ -1671,7 +1844,7 @@
</span><span class="cx">
</span><span class="cx"> @classmethod
</span><span class="cx"> def exclusive(cls, table):
</span><del>- return cls(table, 'exclusive')
</del><ins>+ return cls(table, "exclusive")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="lines">@@ -1680,13 +1853,16 @@
</span><span class="cx"> # concurrency would require some kind of locking statement here.
</span><span class="cx"> # BEGIN IMMEDIATE maybe, if that's okay in the middle of a
</span><span class="cx"> # transaction or repeatedly?
</span><del>- return SQLFragment('select null')
- return SQLFragment('lock table ').append(
- self.table.subSQL(queryGenerator, [self.table])).append(
- SQLFragment(' in %s mode' % (self.mode,)))
</del><ins>+ return SQLFragment("select null")
</ins><span class="cx">
</span><ins>+ return SQLFragment("lock table ").append(
+ self.table.subSQL(queryGenerator, [self.table])
+ ).append(
+ SQLFragment(" in %s mode" % (self.mode,))
+ )
</ins><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class DatabaseLock(_LockingStatement):
</span><span class="cx"> """
</span><span class="cx"> An SQL exclusive session level advisory lock
</span><span class="lines">@@ -1694,7 +1870,7 @@
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> assert(queryGenerator.dialect == POSTGRES_DIALECT)
</span><del>- return SQLFragment('select pg_advisory_lock(1)')
</del><ins>+ return SQLFragment("select pg_advisory_lock(1)")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def on(self, txn, *a, **kw):
</span><span class="lines">@@ -1715,7 +1891,7 @@
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><span class="cx"> assert(queryGenerator.dialect == POSTGRES_DIALECT)
</span><del>- return SQLFragment('select pg_advisory_unlock(1)')
</del><ins>+ return SQLFragment("select pg_advisory_unlock(1)")
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def on(self, txn, *a, **kw):
</span><span class="lines">@@ -1731,7 +1907,7 @@
</span><span class="cx">
</span><span class="cx"> class Savepoint(_LockingStatement):
</span><span class="cx"> """
</span><del>- An SQL 'savepoint' statement.
</del><ins>+ An SQL C{savepoint} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, name):
</span><span class="lines">@@ -1739,13 +1915,13 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><del>- return SQLFragment('savepoint %s' % (self.name,))
</del><ins>+ return SQLFragment("savepoint %s" % (self.name,))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class RollbackToSavepoint(_LockingStatement):
</span><span class="cx"> """
</span><del>- An SQL 'rollback to savepoint' statement.
</del><ins>+ An SQL C{rollback to savepoint} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, name):
</span><span class="lines">@@ -1753,13 +1929,13 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><del>- return SQLFragment('rollback to savepoint %s' % (self.name,))
</del><ins>+ return SQLFragment("rollback to savepoint %s" % (self.name,))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class ReleaseSavepoint(_LockingStatement):
</span><span class="cx"> """
</span><del>- An SQL 'release savepoint' statement.
</del><ins>+ An SQL C{release savepoint} statement.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, name):
</span><span class="lines">@@ -1767,7 +1943,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def _toSQL(self, queryGenerator):
</span><del>- return SQLFragment('release savepoint %s' % (self.name,))
</del><ins>+ return SQLFragment("release savepoint %s" % (self.name,))
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1787,7 +1963,7 @@
</span><span class="cx">
</span><span class="cx"> def release(self, txn):
</span><span class="cx"> if txn.dialect == ORACLE_DIALECT:
</span><del>- # There is no 'release savepoint' statement in oracle, but then, we
</del><ins>+ # There is no "release savepoint" statement in oracle, but then, we
</ins><span class="cx"> # don't need it because there's no resource to manage. Just don't
</span><span class="cx"> # do anything.
</span><span class="cx"> return NoOp()
</span><span class="lines">@@ -1821,13 +1997,17 @@
</span><span class="cx"> if isinstance(parameter, Parameter):
</span><span class="cx"> if parameter.count is not None:
</span><span class="cx"> if parameter.count != len(kw[parameter.name]):
</span><del>- raise DALError("Number of place holders does not match number of items to bind")
</del><ins>+ raise DALError(
+ "Number of place holders does not match "
+ "number of items to bind"
+ )
</ins><span class="cx"> for item in kw[parameter.name]:
</span><span class="cx"> params.append(item)
</span><span class="cx"> else:
</span><span class="cx"> params.append(kw[parameter.name])
</span><span class="cx"> else:
</span><span class="cx"> params.append(parameter)
</span><ins>+
</ins><span class="cx"> return SQLFragment(self.text, params)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1885,7 +2065,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def __repr__(self):
</span><del>- return 'Parameter(%r)' % (self.name,)
</del><ins>+ return "Parameter(%r)" % (self.name,)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1897,8 +2077,9 @@
</span><span class="cx">
</span><span class="cx"> # You can't insert a column with no rows. In SQL that just isn't valid syntax,
</span><span class="cx"> # and in this DAL you need at least one key or we can't tell what table you're
</span><del>-# talking about. Luckily there's the 'default' keyword to the rescue, which, in
-# the context of an INSERT statement means 'use the default value explicitly'.
</del><ins>+# talking about. Luckily there's the C{default} keyword to the rescue, which,
+# in the context of an INSERT statement means "use the default value
+# explicitly".
</ins><span class="cx"> # (Although this is a special keyword in a CREATE statement, in an INSERT it
</span><span class="cx"> # behaves like an expression to the best of my knowledge.)
</span><del>-default = NamedValue('default')
</del><ins>+default = NamedValue("default")
</ins></span></pre></div>
<a id="twexttrunktwextenterprisedaltesttest_parseschemapy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/test/test_parseschema.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/test/test_parseschema.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/test/test_parseschema.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> from twisted.trial.unittest import TestCase
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class SchemaTestHelper(object):
</span><span class="cx"> """
</span><span class="cx"> Mix-in that can parse a schema from a string.
</span><span class="lines">@@ -218,7 +219,8 @@
</span><span class="cx"> "create table sample (example integer unique);",
</span><span class="cx"> "create table sample (example integer, unique (example));",
</span><span class="cx"> "create table sample "
</span><del>- "(example integer, constraint unique_example unique (example))"]:
</del><ins>+ "(example integer, constraint unique_example unique (example))"
+ ]:
</ins><span class="cx"> s = self.schemaFromString(identicalSchema)
</span><span class="cx"> table = s.tableNamed('sample')
</span><span class="cx"> column = table.columnNamed('example')
</span><span class="lines">@@ -320,8 +322,8 @@
</span><span class="cx">
</span><span class="cx"> def test_deleteAction(self):
</span><span class="cx"> """
</span><del>- A column with an 'on delete cascade' constraint will have its C{cascade}
- attribute set to True.
</del><ins>+ A column with an 'on delete cascade' constraint will have its
+ C{cascade} attribute set to True.
</ins><span class="cx"> """
</span><span class="cx"> s = self.schemaFromString(
</span><span class="cx"> """
</span><span class="lines">@@ -329,11 +331,24 @@
</span><span class="cx"> create table c2 (d2 integer references a1 on delete cascade);
</span><span class="cx"> create table e3 (f3 integer references a1 on delete set null);
</span><span class="cx"> create table g4 (h4 integer references a1 on delete set default);
</span><del>- """)
- self.assertEquals(s.tableNamed("a1").columnNamed("b1").deleteAction, None)
- self.assertEquals(s.tableNamed("c2").columnNamed("d2").deleteAction, "cascade")
- self.assertEquals(s.tableNamed("e3").columnNamed("f3").deleteAction, "set null")
- self.assertEquals(s.tableNamed("g4").columnNamed("h4").deleteAction, "set default")
</del><ins>+ """
+ )
+ self.assertEquals(
+ s.tableNamed("a1").columnNamed("b1").deleteAction,
+ None
+ )
+ self.assertEquals(
+ s.tableNamed("c2").columnNamed("d2").deleteAction,
+ "cascade"
+ )
+ self.assertEquals(
+ s.tableNamed("e3").columnNamed("f3").deleteAction,
+ "set null"
+ )
+ self.assertEquals(
+ s.tableNamed("g4").columnNamed("h4").deleteAction,
+ "set default"
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_indexes(self):
</span><span class="lines">@@ -350,8 +365,8 @@
</span><span class="cx"> create index idx_a_b on a(b);
</span><span class="cx"> create index idx_a_b_c on a (c, b);
</span><span class="cx"> create index idx_c on z using btree (c);
</span><del>- """)
-
</del><ins>+ """
+ )
</ins><span class="cx"> a = s.tableNamed("a")
</span><span class="cx"> b = s.indexNamed("idx_a_b")
</span><span class="cx"> bc = s.indexNamed('idx_a_b_c')
</span><span class="lines">@@ -373,11 +388,14 @@
</span><span class="cx">
</span><span class="cx"> create unique index idx_a_c on a(c);
</span><span class="cx"> create index idx_a_b_c on a (c, b);
</span><del>- """)
-
- self.assertEqual(set([pseudo.name for pseudo in s.pseudoIndexes()]), set((
- "a-unique:(c)",
- "a:(c,b)",
- "a-unique:(b)",
- "z-unique:(c)",
- )))
</del><ins>+ """
+ )
+ self.assertEqual(
+ set([pseudo.name for pseudo in s.pseudoIndexes()]),
+ set((
+ "a-unique:(c)",
+ "a:(c,b)",
+ "a-unique:(b)",
+ "z-unique:(c)",
+ ))
+ )
</ins></span></pre></div>
<a id="twexttrunktwextenterprisedaltesttest_recordpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/test/test_record.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/test/test_record.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/test/test_record.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> sth = SchemaTestHelper()
</span><del>-sth.id = lambda : __name__
</del><ins>+sth.id = lambda: __name__
</ins><span class="cx"> schemaString = """
</span><span class="cx"> create table ALPHA (BETA integer primary key, GAMMA text);
</span><span class="cx"> create table DELTA (PHI integer primary key default (nextval('myseq')),
</span><span class="lines">@@ -88,10 +88,12 @@
</span><span class="cx"> txn = self.pool.connection()
</span><span class="cx"> yield txn.execSQL("insert into ALPHA values (:1, :2)", [234, "one"])
</span><span class="cx"> yield txn.execSQL("insert into ALPHA values (:1, :2)", [456, "two"])
</span><ins>+
</ins><span class="cx"> rec = yield TestRecord.load(txn, 456)
</span><span class="cx"> self.assertIsInstance(rec, TestRecord)
</span><span class="cx"> self.assertEquals(rec.beta, 456)
</span><span class="cx"> self.assertEquals(rec.gamma, "two")
</span><ins>+
</ins><span class="cx"> rec2 = yield TestRecord.load(txn, 234)
</span><span class="cx"> self.assertIsInstance(rec2, TestRecord)
</span><span class="cx"> self.assertEqual(rec2.beta, 234)
</span><span class="lines">@@ -115,9 +117,11 @@
</span><span class="cx"> be created in the database.
</span><span class="cx"> """
</span><span class="cx"> txn = self.pool.connection()
</span><ins>+
</ins><span class="cx"> rec = yield TestRecord.create(txn, beta=3, gamma=u'epsilon')
</span><span class="cx"> self.assertEquals(rec.beta, 3)
</span><span class="cx"> self.assertEqual(rec.gamma, u'epsilon')
</span><ins>+
</ins><span class="cx"> rows = yield txn.execSQL("select BETA, GAMMA from ALPHA")
</span><span class="cx"> self.assertEqual(rows, [tuple([3, u'epsilon'])])
</span><span class="cx">
</span><span class="lines">@@ -129,11 +133,14 @@
</span><span class="cx"> be deleted in the database.
</span><span class="cx"> """
</span><span class="cx"> txn = self.pool.connection()
</span><ins>+
</ins><span class="cx"> def mkrow(beta, gamma):
</span><span class="cx"> return txn.execSQL("insert into ALPHA values (:1, :2)",
</span><span class="cx"> [beta, gamma])
</span><del>- yield gatherResults([mkrow(123, u"one"), mkrow(234, u"two"),
- mkrow(345, u"three")])
</del><ins>+
+ yield gatherResults(
+ [mkrow(123, u"one"), mkrow(234, u"two"), mkrow(345, u"three")]
+ )
</ins><span class="cx"> tr = yield TestRecord.load(txn, 234)
</span><span class="cx"> yield tr.delete()
</span><span class="cx"> rows = yield txn.execSQL("select BETA, GAMMA from ALPHA order by BETA")
</span><span class="lines">@@ -185,12 +192,19 @@
</span><span class="cx"> txn = self.pool.connection()
</span><span class="cx"> # Create ...
</span><span class="cx"> rec = yield TestAutoRecord.create(txn, epsilon=1)
</span><del>- self.assertEquals(rec.zeta, datetime.datetime(2012, 12, 12, 12, 12, 12))
</del><ins>+ self.assertEquals(
+ rec.zeta,
+ datetime.datetime(2012, 12, 12, 12, 12, 12)
+ )
</ins><span class="cx"> yield txn.commit()
</span><span class="cx"> # ... should have the same effect as loading.
</span><ins>+
</ins><span class="cx"> txn = self.pool.connection()
</span><span class="cx"> rec = (yield TestAutoRecord.all(txn))[0]
</span><del>- self.assertEquals(rec.zeta, datetime.datetime(2012, 12, 12, 12, 12, 12))
</del><ins>+ self.assertEquals(
+ rec.zeta,
+ datetime.datetime(2012, 12, 12, 12, 12, 12)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @inlineCallbacks
</span><span class="lines">@@ -200,11 +214,14 @@
</span><span class="cx"> don't map to any column), it raises a L{TypeError}.
</span><span class="cx"> """
</span><span class="cx"> txn = self.pool.connection()
</span><del>- te = yield self.failUnlessFailure(TestRecord.create(
- txn, beta=3, gamma=u'three',
- extraBonusAttribute=u'nope',
- otherBonusAttribute=4321,
- ), TypeError)
</del><ins>+ te = yield self.failUnlessFailure(
+ TestRecord.create(
+ txn, beta=3, gamma=u'three',
+ extraBonusAttribute=u'nope',
+ otherBonusAttribute=4321,
+ ),
+ TypeError
+ )
</ins><span class="cx"> self.assertIn("extraBonusAttribute, otherBonusAttribute", str(te))
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -233,8 +250,10 @@
</span><span class="cx"> """
</span><span class="cx"> txn = self.pool.connection()
</span><span class="cx"> rec = yield TestRecord.create(txn, beta=7, gamma=u'what')
</span><ins>+
</ins><span class="cx"> def setit():
</span><span class="cx"> rec.beta = 12
</span><ins>+
</ins><span class="cx"> ro = self.assertRaises(ReadOnly, setit)
</span><span class="cx"> self.assertEqual(rec.beta, 7)
</span><span class="cx"> self.assertIn("SQL-backed attribute 'TestRecord.beta' is read-only. "
</span><span class="lines">@@ -318,11 +337,14 @@
</span><span class="cx"> yield txn.execSQL("insert into ALPHA values (:1, :2)",
</span><span class="cx"> [beta, gamma])
</span><span class="cx">
</span><del>- records = yield TestRecord.query(txn, TestRecord.gamma == u"three",
- TestRecord.beta)
</del><ins>+ records = yield TestRecord.query(
+ txn, TestRecord.gamma == u"three", TestRecord.beta
+ )
</ins><span class="cx"> self.assertEqual([record.beta for record in records], [345, 356])
</span><del>- records = yield TestRecord.query(txn, TestRecord.gamma == u"three",
- TestRecord.beta, ascending=False)
</del><ins>+
+ records = yield TestRecord.query(
+ txn, TestRecord.gamma == u"three", TestRecord.beta, ascending=False
+ )
</ins><span class="cx"> self.assertEqual([record.beta for record in records], [356, 345])
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -332,15 +354,25 @@
</span><span class="cx"> A L{Record} may be loaded and deleted atomically, with L{Record.pop}.
</span><span class="cx"> """
</span><span class="cx"> txn = self.pool.connection()
</span><del>- for beta, gamma in [(123, u"one"), (234, u"two"), (345, u"three"),
- (356, u"three"), (456, u"four")]:
- yield txn.execSQL("insert into ALPHA values (:1, :2)",
- [beta, gamma])
</del><ins>+ for beta, gamma in [
+ (123, u"one"),
+ (234, u"two"),
+ (345, u"three"),
+ (356, u"three"),
+ (456, u"four"),
+ ]:
+ yield txn.execSQL(
+ "insert into ALPHA values (:1, :2)", [beta, gamma]
+ )
+
</ins><span class="cx"> rec = yield TestRecord.pop(txn, 234)
</span><span class="cx"> self.assertEqual(rec.gamma, u'two')
</span><del>- self.assertEqual((yield txn.execSQL("select count(*) from ALPHA "
- "where BETA = :1", [234])),
- [tuple([0])])
</del><ins>+ self.assertEqual(
+ (yield txn.execSQL(
+ "select count(*) from ALPHA where BETA = :1", [234]
+ )),
+ [tuple([0])]
+ )
</ins><span class="cx"> yield self.failUnlessFailure(TestRecord.pop(txn, 234), NoSuchRecord)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -349,6 +381,15 @@
</span><span class="cx"> The naming convention maps columns C{LIKE_THIS} to be attributes
</span><span class="cx"> C{likeThis}.
</span><span class="cx"> """
</span><del>- self.assertEqual(Record.namingConvention(u"like_this"), "likeThis")
- self.assertEqual(Record.namingConvention(u"LIKE_THIS"), "likeThis")
- self.assertEqual(Record.namingConvention(u"LIKE_THIS_ID"), "likeThisID")
</del><ins>+ self.assertEqual(
+ Record.namingConvention(u"like_this"),
+ "likeThis"
+ )
+ self.assertEqual(
+ Record.namingConvention(u"LIKE_THIS"),
+ "likeThis"
+ )
+ self.assertEqual(
+ Record.namingConvention(u"LIKE_THIS_ID"),
+ "likeThisID"
+ )
</ins></span></pre></div>
<a id="twexttrunktwextenterprisedaltesttest_sqlsyntaxpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/dal/test/test_sqlsyntax.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/dal/test/test_sqlsyntax.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/dal/test/test_sqlsyntax.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -26,13 +26,15 @@
</span><span class="cx"> Savepoint, RollbackToSavepoint, ReleaseSavepoint, SavepointAction,
</span><span class="cx"> Union, Intersect, Except, SetExpression, DALError,
</span><span class="cx"> ResultAliasSyntax, Count, QueryGenerator, ALL_COLUMNS,
</span><del>- DatabaseLock, DatabaseUnlock)
</del><ins>+ DatabaseLock, DatabaseUnlock
+)
</ins><span class="cx"> from twext.enterprise.dal.syntax import FixedPlaceholder, NumericPlaceholder
</span><span class="cx"> from twext.enterprise.dal.syntax import Function
</span><span class="cx"> from twext.enterprise.dal.syntax import SchemaSyntax
</span><span class="cx"> from twext.enterprise.dal.test.test_parseschema import SchemaTestHelper
</span><del>-from twext.enterprise.ienterprise import (POSTGRES_DIALECT, ORACLE_DIALECT,
- SQLITE_DIALECT)
</del><ins>+from twext.enterprise.ienterprise import (
+ POSTGRES_DIALECT, ORACLE_DIALECT, SQLITE_DIALECT
+)
</ins><span class="cx"> from twext.enterprise.test.test_adbapi2 import ConnectionPoolHelper
</span><span class="cx"> from twext.enterprise.test.test_adbapi2 import NetworkedPoolHelper
</span><span class="cx"> from twext.enterprise.test.test_adbapi2 import resultOf, AssertResultHelper
</span><span class="lines">@@ -50,15 +52,15 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> def __init__(self, paramstyle):
</span><del>- self.paramstyle = 'qmark'
</del><ins>+ self.paramstyle = "qmark"
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> class FakeCXOracleModule(object):
</span><del>- NUMBER = 'the NUMBER type'
- STRING = 'a string type (for varchars)'
- NCLOB = 'the NCLOB type. (for text)'
- TIMESTAMP = 'for timestamps!'
</del><ins>+ NUMBER = "the NUMBER type"
+ STRING = "a string type (for varchars)"
+ NCLOB = "the NCLOB type. (for text)"
+ TIMESTAMP = "for timestamps!"
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -68,11 +70,11 @@
</span><span class="cx"> """
</span><span class="cx"> counter = 0
</span><span class="cx">
</span><del>- def __init__(self, dialect=SQLITE_DIALECT, paramstyle='numeric'):
</del><ins>+ def __init__(self, dialect=SQLITE_DIALECT, paramstyle="numeric"):
</ins><span class="cx"> self.execed = []
</span><span class="cx"> self.pendingResults = []
</span><span class="cx"> self.dialect = SQLITE_DIALECT
</span><del>- self.paramstyle = 'numeric'
</del><ins>+ self.paramstyle = "numeric"
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def nextResult(self, result):
</span><span class="lines">@@ -104,12 +106,13 @@
</span><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> dialect = ORACLE_DIALECT
</span><del>- paramstyle = 'numeric'
</del><ins>+ paramstyle = "numeric"
</ins><span class="cx">
</span><span class="cx"> def execSQL(self, text, params, exc):
</span><span class="cx"> return succeed([[None, None]])
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> EXAMPLE_SCHEMA = """
</span><span class="cx"> create sequence A_SEQ;
</span><span class="cx"> create table FOO (BAR integer, BAZ varchar(255));
</span><span class="lines">@@ -123,6 +126,8 @@
</span><span class="cx"> ANUMBER integer);
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class ExampleSchemaHelper(SchemaTestHelper):
</span><span class="cx"> """
</span><span class="cx"> setUp implementor.
</span><span class="lines">@@ -140,11 +145,13 @@
</span><span class="cx">
</span><span class="cx"> def test_simplestSelect(self):
</span><span class="cx"> """
</span><del>- L{Select} generates a 'select' statement, by default, asking for all
</del><ins>+ L{Select} generates a C{select} statement, by default, asking for all
</ins><span class="cx"> rows in a table.
</span><span class="cx"> """
</span><del>- self.assertEquals(Select(From=self.schema.FOO).toSQL(),
- SQLFragment("select * from FOO", []))
</del><ins>+ self.assertEquals(
+ Select(From=self.schema.FOO).toSQL(),
+ SQLFragment("select * from FOO", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_tableSyntaxFromSchemaSyntaxCompare(self):
</span><span class="lines">@@ -158,34 +165,44 @@
</span><span class="cx">
</span><span class="cx"> def test_simpleWhereClause(self):
</span><span class="cx"> """
</span><del>- L{Select} generates a 'select' statement with a 'where' clause
</del><ins>+ L{Select} generates a C{select} statement with a C{where} clause
</ins><span class="cx"> containing an expression.
</span><span class="cx"> """
</span><del>- self.assertEquals(Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR == 1).toSQL(),
- SQLFragment("select * from FOO where BAR = ?", [1]))
</del><ins>+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == 1
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR = ?", [1])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_alternateMetadata(self):
</span><span class="cx"> """
</span><del>- L{Select} generates a 'select' statement with the specified placeholder
- syntax when explicitly given L{ConnectionMetadata} which specifies a
- placeholder.
</del><ins>+ L{Select} generates a C{select} statement with the specified
+ placeholder syntax when explicitly given L{ConnectionMetadata} which
+ specifies a placeholder.
</ins><span class="cx"> """
</span><del>- self.assertEquals(Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR == 1).toSQL(
- QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("$$"))),
- SQLFragment("select * from FOO where BAR = $$", [1]))
</del><ins>+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == 1
+ ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("$$"))),
+ SQLFragment("select * from FOO where BAR = $$", [1])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_columnComparison(self):
</span><span class="cx"> """
</span><del>- L{Select} generates a 'select' statement which compares columns.
</del><ins>+ L{Select} generates a C{select} statement which compares columns.
</ins><span class="cx"> """
</span><del>- self.assertEquals(Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR ==
- self.schema.FOO.BAZ).toSQL(),
- SQLFragment("select * from FOO where BAR = BAZ", []))
</del><ins>+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == self.schema.FOO.BAZ
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR = BAZ", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_comparisonTestErrorPrevention(self):
</span><span class="lines">@@ -199,55 +216,65 @@
</span><span class="cx"> """
</span><span class="cx"> def sampleComparison():
</span><span class="cx"> if self.schema.FOO.BAR > self.schema.FOO.BAZ:
</span><del>- return 'comparison should not succeed'
</del><ins>+ return "comparison should not succeed"
</ins><span class="cx"> self.assertRaises(DALError, sampleComparison)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_compareWithNULL(self):
</span><span class="cx"> """
</span><del>- Comparing a column with None results in the generation of an 'is null'
- or 'is not null' SQL statement.
</del><ins>+ Comparing a column with None results in the generation of an C{is null}
+ or C{is not null} SQL statement.
</ins><span class="cx"> """
</span><del>- self.assertEquals(Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR ==
- None).toSQL(),
- SQLFragment(
- "select * from FOO where BAR is null", []))
- self.assertEquals(Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR !=
- None).toSQL(),
- SQLFragment(
- "select * from FOO where BAR is not null", []))
</del><ins>+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == None
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR is null", [])
+ )
+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR != None
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR is not null", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_compareWithEmptyStringOracleSpecialCase(self):
</span><span class="cx"> """
</span><del>- Oracle considers the empty string to be a NULL value, so comparisons
- with the empty string should be 'is NULL' comparisons.
</del><ins>+ Oracle considers the empty string to be a C{NULL} value, so comparisons
+ with the empty string should be C{is NULL} comparisons.
</ins><span class="cx"> """
</span><span class="cx"> # Sanity check: let's make sure that the non-oracle case looks normal.
</span><del>- self.assertEquals(Select(
- From=self.schema.FOO,
- Where=self.schema.FOO.BAR == '').toSQL(),
- SQLFragment(
- "select * from FOO where BAR = ?", [""]))
- self.assertEquals(Select(
- From=self.schema.FOO,
- Where=self.schema.FOO.BAR != '').toSQL(),
- SQLFragment(
- "select * from FOO where BAR != ?", [""]))
- self.assertEquals(Select(
- From=self.schema.FOO,
- Where=self.schema.FOO.BAR == ''
- ).toSQL(QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())),
- SQLFragment(
- "select * from FOO where BAR is null", []))
- self.assertEquals(Select(
- From=self.schema.FOO,
- Where=self.schema.FOO.BAR != ''
- ).toSQL(QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())),
- SQLFragment(
- "select * from FOO where BAR is not null", []))
</del><ins>+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == ""
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR = ?", [""])
+ )
+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR != ""
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR != ?", [""])
+ )
+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR == ""
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())),
+ SQLFragment("select * from FOO where BAR is null", [])
+ )
+ self.assertEquals(
+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR != ""
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())),
+ SQLFragment("select * from FOO where BAR is not null", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_compoundWhere(self):
</span><span class="lines">@@ -255,20 +282,24 @@
</span><span class="cx"> L{Select.And} and L{Select.Or} will return compound columns.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- Where=(self.schema.FOO.BAR < 2).Or(
- self.schema.FOO.BAR > 5)).toSQL(),
- SQLFragment("select * from FOO where BAR < ? or BAR > ?", [2, 5]))
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=(self.schema.FOO.BAR < 2).Or(self.schema.FOO.BAR > 5)
+ ).toSQL(),
+ SQLFragment("select * from FOO where BAR < ? or BAR > ?", [2, 5])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_orderBy(self):
</span><span class="cx"> """
</span><del>- L{Select}'s L{OrderBy} parameter generates an 'order by' clause for a
- 'select' statement.
</del><ins>+ L{Select}'s L{OrderBy} parameter generates an C{order by} clause for a
+ C{select} statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- OrderBy=self.schema.FOO.BAR).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ OrderBy=self.schema.FOO.BAR
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO order by BAR")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -279,23 +310,29 @@
</span><span class="cx"> order for query results with an OrderBy clause.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- OrderBy=self.schema.FOO.BAR,
- Ascending=False).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ OrderBy=self.schema.FOO.BAR,
+ Ascending=False
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO order by BAR desc")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- OrderBy=self.schema.FOO.BAR,
- Ascending=True).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ OrderBy=self.schema.FOO.BAR,
+ Ascending=True
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO order by BAR asc")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- OrderBy=[self.schema.FOO.BAR, self.schema.FOO.BAZ],
- Ascending=True).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ OrderBy=[self.schema.FOO.BAR, self.schema.FOO.BAZ],
+ Ascending=True
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO order by BAR, BAZ asc")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -308,16 +345,17 @@
</span><span class="cx"> columns.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- OrderBy=Tuple([self.schema.FOO.BAR,
- self.schema.FOO.BAZ])).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ OrderBy=Tuple([self.schema.FOO.BAR, self.schema.FOO.BAZ])
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO order by BAR, BAZ")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_forUpdate(self):
</span><span class="cx"> """
</span><del>- L{Select}'s L{ForUpdate} parameter generates a 'for update' clause at
</del><ins>+ L{Select}'s L{ForUpdate} parameter generates a C{for update} clause at
</ins><span class="cx"> the end of the query.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -328,12 +366,14 @@
</span><span class="cx">
</span><span class="cx"> def test_groupBy(self):
</span><span class="cx"> """
</span><del>- L{Select}'s L{GroupBy} parameter generates a 'group by' clause for a
- 'select' statement.
</del><ins>+ L{Select}'s L{GroupBy} parameter generates a C{group by} clause for a
+ C{select} statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- GroupBy=self.schema.FOO.BAR).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ GroupBy=self.schema.FOO.BAR
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO group by BAR")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -343,29 +383,34 @@
</span><span class="cx"> L{Select}'s L{GroupBy} parameter can accept multiple columns in a list.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- GroupBy=[self.schema.FOO.BAR,
- self.schema.FOO.BAZ]).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ GroupBy=[self.schema.FOO.BAR, self.schema.FOO.BAZ]
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO group by BAR, BAZ")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_joinClause(self):
</span><span class="cx"> """
</span><del>- A table's .join() method returns a join statement in a SELECT.
</del><ins>+ A table's C{.join()} method returns a join statement in a C{SELECT}.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO.join(
- self.schema.BOZ, self.schema.FOO.BAR ==
- self.schema.BOZ.QUX)).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO.join(
+ self.schema.BOZ,
+ self.schema.FOO.BAR == self.schema.BOZ.QUX
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO join BOZ on BAR = QUX", [])
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_crossJoin(self):
</span><span class="cx"> """
</span><del>- A join with no clause specified will generate a cross join. (This is an
- explicit synonym for an implicit join: i.e. 'select * from FOO, BAR'.)
</del><ins>+ A join with no clause specified will generate a cross join. (This is
+ AN explicit synonym for an implicit join: i.e. C{select * from FOO,
+ BAR}.)
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(From=self.schema.FOO.join(self.schema.BOZ)).toSQL(),
</span><span class="lines">@@ -378,32 +423,39 @@
</span><span class="cx"> L{Join.join} will result in a multi-table join.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR,
- self.schema.BOZ.QUX],
- From=self.schema.FOO
- .join(self.schema.BOZ).join(self.schema.OTHER)).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAR, self.schema.BOZ.QUX],
+ From=self.schema.FOO
+ .join(self.schema.BOZ)
+ .join(self.schema.OTHER)
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><del>- "select FOO.BAR, QUX from FOO "
- "cross join BOZ cross join OTHER")
</del><ins>+ "select FOO.BAR, QUX from FOO cross join BOZ cross join OTHER"
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_multiJoin(self):
</span><span class="cx"> """
</span><span class="cx"> L{Join.join} has the same signature as L{TableSyntax.join} and supports
</span><del>- the same 'on' and 'type' arguments.
</del><ins>+ the same C{on} and C{type} arguments.
</ins><span class="cx"> """
</span><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR],
- From=self.schema.FOO.join(
- self.schema.BOZ).join(
- self.schema.OTHER,
- self.schema.OTHER.BAR == self.schema.FOO.BAR,
- 'left outer')).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO.join(
+ self.schema.BOZ
+ ).join(
+ self.schema.OTHER,
+ self.schema.OTHER.BAR == self.schema.FOO.BAR,
+ "left outer"
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "select FOO.BAR from FOO cross join BOZ left outer join OTHER "
</span><del>- "on OTHER.BAR = FOO.BAR")
</del><ins>+ "on OTHER.BAR = FOO.BAR"
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -441,10 +493,14 @@
</span><span class="cx"> fooPrime = foo.alias()
</span><span class="cx"> fooPrimePrime = foo.alias()
</span><span class="cx"> self.assertEquals(
</span><del>- Select([fooPrime.BAR, fooPrimePrime.BAR],
- From=fooPrime.join(fooPrimePrime)).toSQL(),
- SQLFragment("select alias1.BAR, alias2.BAR "
- "from FOO alias1 cross join FOO alias2")
</del><ins>+ Select(
+ [fooPrime.BAR, fooPrimePrime.BAR],
+ From=fooPrime.join(fooPrimePrime)
+ ).toSQL(),
+ SQLFragment(
+ "select alias1.BAR, alias2.BAR "
+ "from FOO alias1 cross join FOO alias2"
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -454,8 +510,7 @@
</span><span class="cx"> output by the SQL statement rather than the all-columns wildcard.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR],
- From=self.schema.FOO).toSQL(),
</del><ins>+ Select([self.schema.FOO.BAR], From=self.schema.FOO).toSQL(),
</ins><span class="cx"> SQLFragment("select BAR from FOO")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -465,8 +520,10 @@
</span><span class="cx"> Iterating a L{TableSyntax} iterates its columns, in the order that they
</span><span class="cx"> are defined.
</span><span class="cx"> """
</span><del>- self.assertEquals(list(self.schema.FOO),
- [self.schema.FOO.BAR, self.schema.FOO.BAZ])
</del><ins>+ self.assertEquals(
+ list(self.schema.FOO),
+ [self.schema.FOO.BAR, self.schema.FOO.BAZ]
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_noColumn(self):
</span><span class="lines">@@ -474,8 +531,7 @@
</span><span class="cx"> Accessing an attribute that is not a defined column on a L{TableSyntax}
</span><span class="cx"> raises an L{AttributeError}.
</span><span class="cx"> """
</span><del>- self.assertRaises(AttributeError,
- lambda : self.schema.FOO.NOT_A_COLUMN)
</del><ins>+ self.assertRaises(AttributeError, lambda: self.schema.FOO.NOT_A_COLUMN)
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_columnAliases(self):
</span><span class="lines">@@ -486,16 +542,23 @@
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(self.schema.FOO.columnAliases(), {})
</span><span class="cx"> self.schema.FOO.ALIAS = self.schema.FOO.BAR
</span><del>- # you comparing ColumnSyntax object results in a ColumnComparison, which
- # you can't test for truth.
- fixedForEquality = dict([(k, v.model) for k, v in
- self.schema.FOO.columnAliases().items()])
- self.assertEquals(fixedForEquality,
- {'ALIAS': self.schema.FOO.BAR.model})
- self.assertIdentical(self.schema.FOO.ALIAS.model,
- self.schema.FOO.BAR.model)
</del><span class="cx">
</span><ins>+ # you comparing ColumnSyntax object results in a ColumnComparison,
+ # which you can't test for truth.
+ fixedForEquality = dict([
+ (k, v.model) for k, v in self.schema.FOO.columnAliases().items()
+ ])
</ins><span class="cx">
</span><ins>+ self.assertEquals(
+ fixedForEquality,
+ {"ALIAS": self.schema.FOO.BAR.model}
+ )
+ self.assertIdentical(
+ self.schema.FOO.ALIAS.model,
+ self.schema.FOO.BAR.model
+ )
+
+
</ins><span class="cx"> def test_multiColumnSelection(self):
</span><span class="cx"> """
</span><span class="cx"> If multiple columns are specified by the argument to L{Select}, those
</span><span class="lines">@@ -503,51 +566,61 @@
</span><span class="cx"> wildcard.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAZ,
- self.schema.FOO.BAR],
- From=self.schema.FOO).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAZ, self.schema.FOO.BAR],
+ From=self.schema.FOO
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select BAZ, BAR from FOO")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_joinColumnSelection(self):
</span><span class="cx"> """
</span><del>- If multiple columns are specified by the argument to L{Select} that uses
- a L{TableSyntax.join}, those will be output by the SQL statement.
</del><ins>+ If multiple columns are specified by the argument to L{Select} that
+ uses a L{TableSyntax.join}, those will be output by the SQL statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAZ,
- self.schema.BOZ.QUX],
- From=self.schema.FOO.join(self.schema.BOZ,
- self.schema.FOO.BAR ==
- self.schema.BOZ.QUX)).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAZ, self.schema.BOZ.QUX],
+ From=self.schema.FOO.join(
+ self.schema.BOZ,
+ self.schema.FOO.BAR == self.schema.BOZ.QUX
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select BAZ, QUX from FOO join BOZ on BAR = QUX")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_tableMismatch(self):
</span><span class="cx"> """
</span><del>- When a column in the 'columns' argument does not match the table from
- the 'From' argument, L{Select} raises a L{TableMismatch}.
</del><ins>+ When a column in the C{columns} argument does not match the table from
+ the C{From} argument, L{Select} raises a L{TableMismatch}.
</ins><span class="cx"> """
</span><del>- self.assertRaises(TableMismatch, Select, [self.schema.BOZ.QUX],
- From=self.schema.FOO)
</del><ins>+ self.assertRaises(
+ TableMismatch,
+ Select, [self.schema.BOZ.QUX], From=self.schema.FOO
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_qualifyNames(self):
</span><span class="cx"> """
</span><del>- When two columns in the FROM clause requested from different tables have
- the same name, the emitted SQL should explicitly disambiguate them.
</del><ins>+ When two columns in the C{from} clause requested from different tables
+ have the same name, the emitted SQL should explicitly disambiguate
+ them.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR,
- self.schema.OTHER.BAR],
- From=self.schema.FOO.join(self.schema.OTHER,
- self.schema.OTHER.FOO_BAR ==
- self.schema.FOO.BAR)).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAR, self.schema.OTHER.BAR],
+ From=self.schema.FOO.join(
+ self.schema.OTHER,
+ self.schema.OTHER.FOO_BAR == self.schema.FOO.BAR
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "select FOO.BAR, OTHER.BAR from FOO "
</span><del>- "join OTHER on FOO_BAR = FOO.BAR"))
</del><ins>+ "join OTHER on FOO_BAR = FOO.BAR"
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_bindParameters(self):
</span><span class="lines">@@ -556,13 +629,16 @@
</span><span class="cx"> L{Parameter} objects in its parameter list replaced with the keyword
</span><span class="cx"> arguments to C{bind}.
</span><span class="cx"> """
</span><del>-
</del><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- Where=(self.schema.FOO.BAR > Parameter("testing")).And(
- self.schema.FOO.BAZ < 7)).toSQL().bind(testing=173),
- SQLFragment("select * from FOO where BAR > ? and BAZ < ?",
- [173, 7]))
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=(self.schema.FOO.BAR > Parameter("testing"))
+ .And(self.schema.FOO.BAZ < 7)
+ ).toSQL().bind(testing=173),
+ SQLFragment(
+ "select * from FOO where BAR > ? and BAZ < ?", [173, 7]
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_rightHandSideExpression(self):
</span><span class="lines">@@ -571,9 +647,10 @@
</span><span class="cx"> comparison operation.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO,
- Where=self.schema.FOO.BAR >
- (self.schema.FOO.BAZ + 3)).toSQL(),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR > (self.schema.FOO.BAZ + 3)
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select * from FOO where BAR > (BAZ + ?)", [3])
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -595,7 +672,10 @@
</span><span class="cx"> ),
</span><span class="cx"> ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</span><span class="cx"> SQLFragment(
</span><del>- "(select * from FOO where BAR = ?) UNION (select * from FOO where BAR = ?)", [1, 2]))
</del><ins>+ "(select * from FOO where BAR = ?) "
+ "UNION (select * from FOO where BAR = ?)", [1, 2]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> # Simple INTERSECT ALL
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -611,7 +691,10 @@
</span><span class="cx"> ),
</span><span class="cx"> ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</span><span class="cx"> SQLFragment(
</span><del>- "(select * from FOO where BAR = ?) INTERSECT ALL (select * from FOO where BAR = ?)", [1, 2]))
</del><ins>+ "(select * from FOO where BAR = ?) "
+ "INTERSECT ALL (select * from FOO where BAR = ?)", [1, 2]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> # Multiple EXCEPTs, not nested, Postgres dialect
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -632,7 +715,11 @@
</span><span class="cx"> ),
</span><span class="cx"> ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</span><span class="cx"> SQLFragment(
</span><del>- "(select * from FOO) EXCEPT DISTINCT (select * from FOO where BAR = ?) EXCEPT DISTINCT (select * from FOO where BAR = ?)", [2, 3]))
</del><ins>+ "(select * from FOO) "
+ "EXCEPT DISTINCT (select * from FOO where BAR = ?) "
+ "EXCEPT DISTINCT (select * from FOO where BAR = ?)", [2, 3]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> # Nested EXCEPTs, Oracle dialect
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -652,7 +739,10 @@
</span><span class="cx"> ),
</span><span class="cx"> ).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</span><span class="cx"> SQLFragment(
</span><del>- "(select * from FOO) MINUS ((select * from FOO where BAR = ?) MINUS (select * from FOO where BAR = ?))", [2, 3]))
</del><ins>+ "(select * from FOO) MINUS ((select * from FOO where BAR = ?) "
+ "MINUS (select * from FOO where BAR = ?))", [2, 3]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> # UNION with order by
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -668,42 +758,49 @@
</span><span class="cx"> OrderBy=self.schema.FOO.BAR,
</span><span class="cx"> ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</span><span class="cx"> SQLFragment(
</span><del>- "(select * from FOO where BAR = ?) UNION (select * from FOO where BAR = ?) order by BAR", [1, 2]))
</del><ins>+ "(select * from FOO where BAR = ?) "
+ "UNION (select * from FOO where BAR = ?) order by BAR", [1, 2]
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_simpleSubSelects(self):
</span><span class="cx"> """
</span><del>- L{Max}C{(column)} produces an object in the 'columns' clause that
- renders the 'max' aggregate in SQL.
</del><ins>+ L{Max}C{(column)} produces an object in the C{columns} clause that
+ renders the C{max} aggregate in SQL.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> [Max(self.schema.BOZ.QUX)],
</span><span class="cx"> From=(Select([self.schema.BOZ.QUX], From=self.schema.BOZ))
</span><span class="cx"> ).toSQL(),
</span><del>- SQLFragment(
- "select max(QUX) from (select QUX from BOZ) genid_1"))
</del><ins>+ SQLFragment("select max(QUX) from (select QUX from BOZ) genid_1")
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> [Count(self.schema.BOZ.QUX)],
</span><span class="cx"> From=(Select([self.schema.BOZ.QUX], From=self.schema.BOZ))
</span><span class="cx"> ).toSQL(),
</span><del>- SQLFragment(
- "select count(QUX) from (select QUX from BOZ) genid_1"))
</del><ins>+ SQLFragment("select count(QUX) from (select QUX from BOZ) genid_1")
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> [Max(self.schema.BOZ.QUX)],
</span><del>- From=(Select([self.schema.BOZ.QUX], From=self.schema.BOZ, As="alias_BAR")),
</del><ins>+ From=(Select(
+ [self.schema.BOZ.QUX],
+ From=self.schema.BOZ,
+ As="alias_BAR"
+ )),
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment(
- "select max(QUX) from (select QUX from BOZ) alias_BAR"))
</del><ins>+ SQLFragment("select max(QUX) from (select QUX from BOZ) alias_BAR")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_setSubSelects(self):
</span><span class="cx"> """
</span><del>- L{SetExpression} in a From sub-select.
</del><ins>+ L{SetExpression} in a C{From} sub-select.
</ins><span class="cx"> """
</span><span class="cx"> # Simple UNION
</span><span class="cx"> self.assertEquals(
</span><span class="lines">@@ -723,7 +820,10 @@
</span><span class="cx"> )
</span><span class="cx"> ).toSQL(),
</span><span class="cx"> SQLFragment(
</span><del>- "select max(BAR) from ((select BAR from FOO where BAR = ?) UNION (select BAR from FOO where BAR = ?)) genid_1", [1, 2]))
</del><ins>+ "select max(BAR) from ((select BAR from FOO where BAR = ?) "
+ "UNION (select BAR from FOO where BAR = ?)) genid_1", [1, 2]
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_selectColumnAliases(self):
</span><span class="lines">@@ -735,101 +835,143 @@
</span><span class="cx"> [ResultAliasSyntax(self.schema.BOZ.QUX, "BOZ_QUX")],
</span><span class="cx"> From=self.schema.BOZ
</span><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select QUX BOZ_QUX from BOZ"))
</del><ins>+ SQLFragment("select QUX BOZ_QUX from BOZ")
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> [ResultAliasSyntax(Max(self.schema.BOZ.QUX))],
</span><span class="cx"> From=self.schema.BOZ
</span><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select max(QUX) genid_1 from BOZ"))
</del><ins>+ SQLFragment("select max(QUX) genid_1 from BOZ")
+ )
</ins><span class="cx">
</span><span class="cx"> alias = ResultAliasSyntax(Max(self.schema.BOZ.QUX))
</span><span class="cx"> self.assertEquals(
</span><del>- Select([alias.columnReference()],
- From=Select(
- [alias],
- From=self.schema.BOZ)
</del><ins>+ Select(
+ [alias.columnReference()],
+ From=Select([alias], From=self.schema.BOZ)
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select genid_1 from (select max(QUX) genid_1 from BOZ) genid_2"))
</del><ins>+ SQLFragment(
+ "select genid_1 from "
+ "(select max(QUX) genid_1 from BOZ) genid_2"
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> alias = ResultAliasSyntax(Len(self.schema.BOZ.QUX))
</span><span class="cx"> self.assertEquals(
</span><del>- Select([alias.columnReference()],
- From=Select(
- [alias],
- From=self.schema.BOZ)
</del><ins>+ Select(
+ [alias.columnReference()],
+ From=Select([alias], From=self.schema.BOZ)
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select genid_1 from (select character_length(QUX) genid_1 from BOZ) genid_2"))
</del><ins>+ SQLFragment(
+ "select genid_1 from "
+ "(select character_length(QUX) genid_1 from BOZ) genid_2"
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_inSubSelect(self):
</span><span class="cx"> """
</span><del>- L{ColumnSyntax.In} returns a sub-expression using the SQL 'in' syntax
</del><ins>+ L{ColumnSyntax.In} returns a sub-expression using the SQL C{in} syntax
</ins><span class="cx"> with a sub-select.
</span><span class="cx"> """
</span><del>- wherein = (self.schema.FOO.BAR.In(
- Select([self.schema.BOZ.QUX], From=self.schema.BOZ)))
</del><ins>+ wherein = self.schema.FOO.BAR.In(
+ Select([self.schema.BOZ.QUX], From=self.schema.BOZ)
+ )
</ins><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(From=self.schema.FOO, Where=wherein).toSQL(),
</span><span class="cx"> SQLFragment(
</span><del>- "select * from FOO where BAR in (select QUX from BOZ)"))
</del><ins>+ "select * from FOO where BAR in (select QUX from BOZ)"
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_inParameter(self):
</span><span class="cx"> """
</span><del>- L{ColumnSyntax.In} returns a sub-expression using the SQL 'in' syntax
</del><ins>+ L{ColumnSyntax.In} returns a sub-expression using the SQL C{in} syntax
</ins><span class="cx"> with parameter list.
</span><span class="cx"> """
</span><span class="cx"> # One item with IN only
</span><del>- items = set(('A',))
</del><ins>+ items = set(("A",))
</ins><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO, Where=self.schema.FOO.BAR.In(Parameter("names", len(items)))).toSQL().bind(names=items),
- SQLFragment(
- "select * from FOO where BAR in (?)", ['A']))
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR.In(
+ Parameter("names", len(items))
+ )
+ ).toSQL().bind(names=items),
+ SQLFragment("select * from FOO where BAR in (?)", ["A"])
+ )
</ins><span class="cx">
</span><span class="cx"> # Two items with IN only
</span><del>- items = set(('A', 'B'))
</del><ins>+ items = set(("A", "B"))
</ins><span class="cx"> self.assertEquals(
</span><del>- Select(From=self.schema.FOO, Where=self.schema.FOO.BAR.In(Parameter("names", len(items)))).toSQL().bind(names=items),
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR.In(
+ Parameter("names", len(items))
+ )
+ ).toSQL().bind(names=items),
</ins><span class="cx"> SQLFragment(
</span><del>- "select * from FOO where BAR in (?, ?)", ['A', 'B']))
</del><ins>+ "select * from FOO where BAR in (?, ?)", ["A", "B"]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> # Two items with preceding AND
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAZ == Parameter('P1')).And(
- self.schema.FOO.BAR.In(Parameter("names", len(items))
- ))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAZ == Parameter("P1")
+ ).And(
+ self.schema.FOO.BAR.In(Parameter("names", len(items)))
+ )
+ )
</ins><span class="cx"> ).toSQL().bind(P1="P1", names=items),
</span><span class="cx"> SQLFragment(
</span><del>- "select * from FOO where BAZ = ? and BAR in (?, ?)", ['P1', 'A', 'B']),
</del><ins>+ "select * from FOO where BAZ = ? and BAR in (?, ?)",
+ ["P1", "A", "B"]
+ ),
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> # Two items with following AND
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAR.In(Parameter("names", len(items))).And(
- self.schema.FOO.BAZ == Parameter('P2')
- ))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAR.In(Parameter("names", len(items)))
+ ).And(
+ self.schema.FOO.BAZ == Parameter("P2")
+ )
+ )
</ins><span class="cx"> ).toSQL().bind(P2="P2", names=items),
</span><span class="cx"> SQLFragment(
</span><del>- "select * from FOO where BAR in (?, ?) and BAZ = ?", ['A', 'B', 'P2']),
</del><ins>+ "select * from FOO where BAR in (?, ?) and BAZ = ?",
+ ["A", "B", "P2"]
+ ),
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> # Two items with preceding OR and following AND
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAZ == Parameter('P1')).Or(
- self.schema.FOO.BAR.In(Parameter("names", len(items))).And(
- self.schema.FOO.BAZ == Parameter('P2')
- ))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAZ == Parameter("P1")
+ ).Or(
+ self.schema.FOO.BAR.In(Parameter("names", len(items)))
+ ).And(
+ self.schema.FOO.BAZ == Parameter("P2")
+ )
+ )
</ins><span class="cx"> ).toSQL().bind(P1="P1", P2="P2", names=items),
</span><span class="cx"> SQLFragment(
</span><del>- "select * from FOO where BAZ = ? or BAR in (?, ?) and BAZ = ?", ['P1', 'A', 'B', 'P2']),
</del><ins>+ "select * from FOO where BAZ = ? or BAR in (?, ?) and BAZ = ?",
+ ["P1", "A", "B", "P2"]
+ ),
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> # Check various error situations
</span><span class="lines">@@ -843,67 +985,78 @@
</span><span class="cx"> # Mismatched count and len(items)
</span><span class="cx"> self.assertRaises(
</span><span class="cx"> DALError,
</span><del>- Select(From=self.schema.FOO, Where=self.schema.FOO.BAR.In(Parameter("names", len(items)))).toSQL().bind,
- names=["a", "b", "c", ]
</del><ins>+ Select(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAR.In(Parameter("names", len(items)))
+ ).toSQL().bind,
+ names=["a", "b", "c"]
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_max(self):
</span><span class="cx"> """
</span><del>- L{Max}C{(column)} produces an object in the 'columns' clause that
- renders the 'max' aggregate in SQL.
</del><ins>+ L{Max}C{(column)} produces an object in the C{columns} clause that
+ renders the C{max} aggregate in SQL.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select([Max(self.schema.BOZ.QUX)], From=self.schema.BOZ).toSQL(),
</span><del>- SQLFragment(
- "select max(QUX) from BOZ"))
</del><ins>+ SQLFragment("select max(QUX) from BOZ")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_countAllCoumns(self):
</span><span class="cx"> """
</span><del>- L{Count}C{(ALL_COLUMNS)} produces an object in the 'columns' clause that
- renders the 'count' in SQL.
</del><ins>+ L{Count}C{(ALL_COLUMNS)} produces an object in the C{columns} clause
+ that renders the C{count} in SQL.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select([Count(ALL_COLUMNS)], From=self.schema.BOZ).toSQL(),
</span><del>- SQLFragment(
- "select count(*) from BOZ"))
</del><ins>+ SQLFragment("select count(*) from BOZ")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_aggregateComparison(self):
</span><span class="cx"> """
</span><del>- L{Max}C{(column) > constant} produces an object in the 'columns' clause
- that renders a comparison to the 'max' aggregate in SQL.
</del><ins>+ L{Max}C{(column) > constant} produces an object in the C{columns}
+ clause that renders a comparison to the C{max} aggregate in SQL.
</ins><span class="cx"> """
</span><del>- self.assertEquals(Select([Max(self.schema.BOZ.QUX) + 12],
- From=self.schema.BOZ).toSQL(),
- SQLFragment("select max(QUX) + ? from BOZ", [12]))
</del><ins>+ self.assertEquals(
+ Select(
+ [Max(self.schema.BOZ.QUX) + 12],
+ From=self.schema.BOZ
+ ).toSQL(),
+ SQLFragment("select max(QUX) + ? from BOZ", [12])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_multiColumnExpression(self):
</span><span class="cx"> """
</span><del>- Multiple columns may be provided in an expression in the 'columns'
- portion of a Select() statement. All arithmetic operators are
</del><ins>+ Multiple columns may be provided in an expression in the C{columns}
+ portion of a C{Select()} statement. All arithmetic operators are
</ins><span class="cx"> supported.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([((self.schema.FOO.BAR + self.schema.FOO.BAZ) / 3) * 7],
- From=self.schema.FOO).toSQL(),
</del><ins>+ Select(
+ [((self.schema.FOO.BAR + self.schema.FOO.BAZ) / 3) * 7],
+ From=self.schema.FOO
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select ((BAR + BAZ) / ?) * ? from FOO", [3, 7])
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_len(self):
</span><span class="cx"> """
</span><del>- Test for the 'Len' function for determining character length of a
</del><ins>+ Test for the L{Len} function for determining character length of a
</ins><span class="cx"> column. (Note that this should be updated to use different techniques
</span><span class="cx"> as necessary in different databases.)
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([Len(self.schema.TEXTUAL.MYTEXT)],
- From=self.schema.TEXTUAL).toSQL(),
- SQLFragment(
- "select character_length(MYTEXT) from TEXTUAL"))
</del><ins>+ Select(
+ [Len(self.schema.TEXTUAL.MYTEXT)],
+ From=self.schema.TEXTUAL
+ ).toSQL(),
+ SQLFragment("select character_length(MYTEXT) from TEXTUAL")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_startswith(self):
</span><span class="lines">@@ -913,8 +1066,8 @@
</span><span class="cx"> as necessary in different databases.)
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([
- self.schema.TEXTUAL.MYTEXT],
</del><ins>+ Select(
+ [self.schema.TEXTUAL.MYTEXT],
</ins><span class="cx"> From=self.schema.TEXTUAL,
</span><span class="cx"> Where=self.schema.TEXTUAL.MYTEXT.StartsWith("test"),
</span><span class="cx"> ).toSQL(),
</span><span class="lines">@@ -932,8 +1085,8 @@
</span><span class="cx"> as necessary in different databases.)
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([
- self.schema.TEXTUAL.MYTEXT],
</del><ins>+ Select(
+ [self.schema.TEXTUAL.MYTEXT],
</ins><span class="cx"> From=self.schema.TEXTUAL,
</span><span class="cx"> Where=self.schema.TEXTUAL.MYTEXT.EndsWith("test"),
</span><span class="cx"> ).toSQL(),
</span><span class="lines">@@ -951,8 +1104,8 @@
</span><span class="cx"> as necessary in different databases.)
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([
- self.schema.TEXTUAL.MYTEXT],
</del><ins>+ Select(
+ [self.schema.TEXTUAL.MYTEXT],
</ins><span class="cx"> From=self.schema.TEXTUAL,
</span><span class="cx"> Where=self.schema.TEXTUAL.MYTEXT.Contains("test"),
</span><span class="cx"> ).toSQL(),
</span><span class="lines">@@ -965,13 +1118,15 @@
</span><span class="cx">
</span><span class="cx"> def test_insert(self):
</span><span class="cx"> """
</span><del>- L{Insert.toSQL} generates an 'insert' statement with all the relevant
</del><ins>+ L{Insert.toSQL} generates an C{insert} statement with all the relevant
</ins><span class="cx"> columns.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: 9}).toSQL(),
- SQLFragment("insert into FOO (BAR, BAZ) values (?, ?)", [23, 9]))
</del><ins>+ Insert(
+ {self.schema.FOO.BAR: 23, self.schema.FOO.BAZ: 9}
+ ).toSQL(),
+ SQLFragment("insert into FOO (BAR, BAZ) values (?, ?)", [23, 9])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_insertNotEnough(self):
</span><span class="lines">@@ -987,49 +1142,52 @@
</span><span class="cx">
</span><span class="cx"> def test_insertReturning(self):
</span><span class="cx"> """
</span><del>- L{Insert}'s C{Return} argument will insert an SQL 'returning' clause.
</del><ins>+ L{Insert}'s C{Return} argument will insert an SQL C{returning} clause.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: 9},
- Return=self.schema.FOO.BAR).toSQL(),
</del><ins>+ Insert(
+ {self.schema.FOO.BAR: 23, self.schema.FOO.BAZ: 9},
+ Return=self.schema.FOO.BAR
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "insert into FOO (BAR, BAZ) values (?, ?) returning BAR",
</span><del>- [23, 9])
</del><ins>+ [23, 9]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_insertMultiReturn(self):
</span><span class="cx"> """
</span><del>- L{Insert}'s C{Return} argument can also be a C{tuple}, which will insert
- an SQL 'returning' clause with multiple columns.
</del><ins>+ L{Insert}'s C{Return} argument can also be a C{tuple}, which will
+ insert an SQL C{returning} clause with multiple columns.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: 9},
- Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)).toSQL(),
</del><ins>+ Insert(
+ {self.schema.FOO.BAR: 23, self.schema.FOO.BAZ: 9},
+ Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "insert into FOO (BAR, BAZ) values (?, ?) returning BAR, BAZ",
</span><del>- [23, 9])
</del><ins>+ [23, 9]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_insertMultiReturnOracle(self):
</span><span class="cx"> """
</span><del>- In Oracle's SQL dialect, the 'returning' clause requires an 'into'
</del><ins>+ In Oracle's SQL dialect, the C{returning} clause requires an C{into}
</ins><span class="cx"> clause indicating where to put the results, as they can't be simply
</span><del>- relayed to the cursor. Further, additional bound variables are required
- to capture the output parameters.
</del><ins>+ relayed to the cursor. Further, additional bound variables are
+ required to capture the output parameters.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.FOO.BAR: 40,
- self.schema.FOO.BAZ: 50},
- Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)).toSQL(
- QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())
- ),
</del><ins>+ Insert(
+ {self.schema.FOO.BAR: 40, self.schema.FOO.BAZ: 50},
+ Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, NumericPlaceholder())),
</ins><span class="cx"> SQLFragment(
</span><del>- "insert into FOO (BAR, BAZ) values (:1, :2) returning BAR, BAZ"
- " into :3, :4",
</del><ins>+ "insert into FOO (BAR, BAZ) values (:1, :2) "
+ "returning BAR, BAZ into :3, :4",
</ins><span class="cx"> [40, 50, Parameter("oracle_out_0"), Parameter("oracle_out_1")]
</span><span class="cx"> )
</span><span class="cx"> )
</span><span class="lines">@@ -1037,21 +1195,21 @@
</span><span class="cx">
</span><span class="cx"> def test_insertMultiReturnSQLite(self):
</span><span class="cx"> """
</span><del>- In SQLite's SQL dialect, there is no 'returning' clause, but given that
- SQLite serializes all SQL transactions, you can rely upon 'select'
- after a write operation to reliably give you exactly what was just
- modified. Therefore, although 'toSQL' won't include any indication of
- the return value, the 'on' method will execute a 'select' statement
- following the insert to retrieve the value.
</del><ins>+ In SQLite's SQL dialect, there is no C{returning} clause, but given
+ that SQLite serializes all SQL transactions, you can rely upon
+ C{select} after a write operation to reliably give you exactly what was
+ just modified. Therefore, although C{toSQL} won't include any
+ indication of the return value, the C{on} method will execute a
+ C{select} statement following the insert to retrieve the value.
</ins><span class="cx"> """
</span><del>- insertStatement = Insert({self.schema.FOO.BAR: 39,
- self.schema.FOO.BAZ: 82},
- Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)
</del><ins>+ insertStatement = Insert(
+ {self.schema.FOO.BAR: 39, self.schema.FOO.BAZ: 82},
+ Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)
</ins><span class="cx"> )
</span><del>- qg = lambda : QueryGenerator(SQLITE_DIALECT, NumericPlaceholder())
- self.assertEquals(insertStatement.toSQL(qg()),
- SQLFragment("insert into FOO (BAR, BAZ) values (:1, :2)",
- [39, 82])
</del><ins>+ qg = lambda: QueryGenerator(SQLITE_DIALECT, NumericPlaceholder())
+ self.assertEquals(
+ insertStatement.toSQL(qg()),
+ SQLFragment("insert into FOO (BAR, BAZ) values (:1, :2)", [39, 82])
</ins><span class="cx"> )
</span><span class="cx"> result = []
</span><span class="cx"> csql = CatchSQL()
</span><span class="lines">@@ -1059,8 +1217,17 @@
</span><span class="cx"> self.assertEqual(result, [2])
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> csql.execed,
</span><del>- [["insert into FOO (BAR, BAZ) values (:1, :2)", [39, 82]],
- ["select BAR, BAZ from FOO where rowid = last_insert_rowid()", []]]
</del><ins>+ [
+ [
+ "insert into FOO (BAR, BAZ) values (:1, :2)",
+ [39, 82]
+ ],
+ [
+ "select BAR, BAZ from FOO "
+ "where rowid = last_insert_rowid()",
+ []
+ ],
+ ]
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1069,8 +1236,9 @@
</span><span class="cx"> Insert a row I{without} a C{Return=} parameter should also work as
</span><span class="cx"> normal in sqlite.
</span><span class="cx"> """
</span><del>- statement = Insert({self.schema.FOO.BAR: 12,
- self.schema.FOO.BAZ: 48})
</del><ins>+ statement = Insert(
+ {self.schema.FOO.BAR: 12, self.schema.FOO.BAZ: 48}
+ )
</ins><span class="cx"> csql = CatchSQL()
</span><span class="cx"> statement.on(csql)
</span><span class="cx"> self.assertEqual(
</span><span class="lines">@@ -1081,23 +1249,27 @@
</span><span class="cx">
</span><span class="cx"> def test_updateReturningSQLite(self):
</span><span class="cx"> """
</span><del>- Since SQLite does not support the SQL 'returning' syntax extension, in
</del><ins>+ Since SQLite does not support the SQL C{returning} syntax extension, in
</ins><span class="cx"> order to preserve the rows that will be modified during an UPDATE
</span><span class="cx"> statement, we must first find the rows that will be affected, then
</span><span class="cx"> update them, then return the rows that were affected. Since we might
</span><del>- be changing even part of the primary key, we use the internal 'rowid'
</del><ins>+ be changing even part of the primary key, we use the internal C{rowid}
</ins><span class="cx"> column to uniquely and reliably identify rows in the sqlite database
</span><span class="cx"> that have been modified.
</span><span class="cx"> """
</span><span class="cx"> csql = CatchSQL()
</span><del>- stmt = Update({self.schema.FOO.BAR: 4321},
- Where=self.schema.FOO.BAZ == 1234,
- Return=self.schema.FOO.BAR)
</del><ins>+ stmt = Update(
+ {self.schema.FOO.BAR: 4321},
+ Where=self.schema.FOO.BAZ == 1234,
+ Return=self.schema.FOO.BAR
+ )
</ins><span class="cx"> csql.nextResult([["sample row id"]])
</span><span class="cx"> result = resultOf(stmt.on(csql))
</span><del>- # Three statements were executed; make sure that the result returned was
- # the result of executing the 3rd (and final) one.
</del><ins>+
+ # Three statements were executed; make sure that the result returned
+ # was the result of executing the 3rd (and final) one.
</ins><span class="cx"> self.assertResultList(result, 3)
</span><ins>+
</ins><span class="cx"> # Check that they were the right statements.
</span><span class="cx"> self.assertEqual(len(csql.execed), 3)
</span><span class="cx"> self.assertEqual(
</span><span class="lines">@@ -1117,18 +1289,22 @@
</span><span class="cx"> def test_updateReturningMultipleValuesSQLite(self):
</span><span class="cx"> """
</span><span class="cx"> When SQLite updates multiple values, it must embed the row ID of each
</span><del>- subsequent value into its second 'where' clause, as there is no way to
</del><ins>+ subsequent value into its second C{where} clause, as there is no way to
</ins><span class="cx"> pass a list of values to a single statement..
</span><span class="cx"> """
</span><span class="cx"> csql = CatchSQL()
</span><del>- stmt = Update({self.schema.FOO.BAR: 4321},
- Where=self.schema.FOO.BAZ == 1234,
- Return=self.schema.FOO.BAR)
</del><ins>+ stmt = Update(
+ {self.schema.FOO.BAR: 4321},
+ Where=self.schema.FOO.BAZ == 1234,
+ Return=self.schema.FOO.BAR
+ )
</ins><span class="cx"> csql.nextResult([["one row id"], ["and another"], ["and one more"]])
</span><span class="cx"> result = resultOf(stmt.on(csql))
</span><del>- # Three statements were executed; make sure that the result returned was
- # the result of executing the 3rd (and final) one.
</del><ins>+
+ # Three statements were executed; make sure that the result returned
+ # was the result of executing the 3rd (and final) one.
</ins><span class="cx"> self.assertResultList(result, 3)
</span><ins>+
</ins><span class="cx"> # Check that they were the right statements.
</span><span class="cx"> self.assertEqual(len(csql.execed), 3)
</span><span class="cx"> self.assertEqual(
</span><span class="lines">@@ -1141,8 +1317,11 @@
</span><span class="cx"> )
</span><span class="cx"> self.assertEqual(
</span><span class="cx"> csql.execed[2],
</span><del>- ["select BAR from FOO where rowid = :1 or rowid = :2 or rowid = :3",
- ["one row id", "and another", "and one more"]]
</del><ins>+ [
+ "select BAR from FOO "
+ "where rowid = :1 or rowid = :2 or rowid = :3",
+ ["one row id", "and another", "and one more"]
+ ]
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1151,8 +1330,11 @@
</span><span class="cx"> When SQLite deletes a value, ...
</span><span class="cx"> """
</span><span class="cx"> csql = CatchSQL()
</span><del>- stmt = Delete(From=self.schema.FOO, Where=self.schema.FOO.BAZ == 1234,
- Return=self.schema.FOO.BAR)
</del><ins>+ stmt = Delete(
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAZ == 1234,
+ Return=self.schema.FOO.BAR
+ )
</ins><span class="cx"> result = resultOf(stmt.on(csql))
</span><span class="cx"> self.assertResultList(result, 1)
</span><span class="cx"> self.assertEqual(len(csql.execed), 2)
</span><span class="lines">@@ -1173,48 +1355,61 @@
</span><span class="cx"> """
</span><span class="cx"> self.assertRaises(
</span><span class="cx"> TableMismatch,
</span><del>- Insert, {self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: 9,
- self.schema.TEXTUAL.MYTEXT: 'hello'}
</del><ins>+ Insert, {
+ self.schema.FOO.BAR: 23,
+ self.schema.FOO.BAZ: 9,
+ self.schema.TEXTUAL.MYTEXT: "hello"
+ }
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_quotingOnKeywordConflict(self):
</span><span class="cx"> """
</span><del>- 'access' is a keyword, so although our schema parser will leniently
- accept it, it must be quoted in any outgoing SQL. (This is only done in
- the Oracle dialect, because it isn't necessary in postgres, and
</del><ins>+ "access" is a keyword, so although our schema parser will leniently
+ accept it, it must be quoted in any outgoing SQL. (This is only done
+ in the Oracle dialect, because it isn't necessary in postgres, and
</ins><span class="cx"> idiosyncratic case-folding rules make it challenging to do it in both.)
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.LEVELS.ACCESS: 1,
- self.schema.LEVELS.USERNAME:
- "hi"}).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</del><ins>+ Insert(
+ {
+ self.schema.LEVELS.ACCESS: 1,
+ self.schema.LEVELS.USERNAME: "hi"
+ }
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</ins><span class="cx"> SQLFragment(
</span><del>- 'insert into LEVELS ("ACCESS", USERNAME) values (?, ?)',
- [1, "hi"])
</del><ins>+ """insert into LEVELS ("ACCESS", USERNAME) values (?, ?)""",
+ [1, "hi"]
+ )
</ins><span class="cx"> )
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.LEVELS.ACCESS: 1,
- self.schema.LEVELS.USERNAME:
- "hi"}).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</del><ins>+ Insert(
+ {
+ self.schema.LEVELS.ACCESS: 1,
+ self.schema.LEVELS.USERNAME: "hi"
+ }
+ ).toSQL(QueryGenerator(POSTGRES_DIALECT, FixedPlaceholder("?"))),
</ins><span class="cx"> SQLFragment(
</span><del>- 'insert into LEVELS (ACCESS, USERNAME) values (?, ?)',
- [1, "hi"])
</del><ins>+ "insert into LEVELS (ACCESS, USERNAME) values (?, ?)",
+ [1, "hi"]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_updateReturning(self):
</span><span class="cx"> """
</span><del>- L{update}'s C{Return} argument will update an SQL 'returning' clause.
</del><ins>+ L{update}'s C{Return} argument will update an SQL C{returning} clause.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Update({self.schema.FOO.BAR: 23},
- self.schema.FOO.BAZ == 43,
- Return=self.schema.FOO.BAR).toSQL(),
</del><ins>+ Update(
+ {self.schema.FOO.BAR: 23},
+ self.schema.FOO.BAZ == 43,
+ Return=self.schema.FOO.BAR
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "update FOO set BAR = ? where BAZ = ? returning BAR",
</span><del>- [23, 43])
</del><ins>+ [23, 43]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1225,9 +1420,11 @@
</span><span class="cx"> """
</span><span class="cx"> self.assertRaises(
</span><span class="cx"> TableMismatch,
</span><del>- Update, {self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: 9,
- self.schema.TEXTUAL.MYTEXT: 'hello'},
</del><ins>+ Update, {
+ self.schema.FOO.BAR: 23,
+ self.schema.FOO.BAZ: 9,
+ self.schema.TEXTUAL.MYTEXT: "hello"
+ },
</ins><span class="cx"> Where=self.schema.FOO.BAZ == 9
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -1240,12 +1437,12 @@
</span><span class="cx"> sqlfunc = Function("hello")
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Update(
</span><del>- {self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: sqlfunc()},
</del><ins>+ {self.schema.FOO.BAR: 23, self.schema.FOO.BAZ: sqlfunc()},
</ins><span class="cx"> Where=self.schema.FOO.BAZ == 9
</span><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("update FOO set BAR = ?, BAZ = hello() "
- "where BAZ = ?", [23, 9])
</del><ins>+ SQLFragment(
+ "update FOO set BAR = ?, BAZ = hello() where BAZ = ?", [23, 9]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1257,165 +1454,186 @@
</span><span class="cx"> sqlfunc = Function("hello")
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Insert(
</span><del>- {self.schema.FOO.BAR: 23,
- self.schema.FOO.BAZ: sqlfunc()},
</del><ins>+ {self.schema.FOO.BAR: 23, self.schema.FOO.BAZ: sqlfunc()},
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("insert into FOO (BAR, BAZ) "
- "values (?, hello())", [23])
</del><ins>+ SQLFragment("insert into FOO (BAR, BAZ) values (?, hello())", [23])
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_deleteReturning(self):
</span><span class="cx"> """
</span><del>- L{Delete}'s C{Return} argument will delete an SQL 'returning' clause.
</del><ins>+ L{Delete}'s C{Return} argument will delete an SQL C{returning} clause.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Delete(self.schema.FOO,
- Where=self.schema.FOO.BAR == 7,
- Return=self.schema.FOO.BAZ).toSQL(),
- SQLFragment(
- "delete from FOO where BAR = ? returning BAZ", [7])
</del><ins>+ Delete(
+ self.schema.FOO,
+ Where=self.schema.FOO.BAR == 7,
+ Return=self.schema.FOO.BAZ
+ ).toSQL(),
+ SQLFragment("delete from FOO where BAR = ? returning BAZ", [7])
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_update(self):
</span><span class="cx"> """
</span><del>- L{Update.toSQL} generates an 'update' statement.
</del><ins>+ L{Update.toSQL} generates an C{update} statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Update({self.schema.FOO.BAR: 4321},
- self.schema.FOO.BAZ == 1234).toSQL(),
- SQLFragment("update FOO set BAR = ? where BAZ = ?", [4321, 1234]))
</del><ins>+ Update(
+ {self.schema.FOO.BAR: 4321},
+ self.schema.FOO.BAZ == 1234
+ ).toSQL(),
+ SQLFragment("update FOO set BAR = ? where BAZ = ?", [4321, 1234])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_delete(self):
</span><span class="cx"> """
</span><del>- L{Delete} generates an SQL 'delete' statement.
</del><ins>+ L{Delete} generates an SQL C{delete} statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Delete(self.schema.FOO,
- Where=self.schema.FOO.BAR == 12).toSQL(),
- SQLFragment(
- "delete from FOO where BAR = ?", [12])
</del><ins>+ Delete(self.schema.FOO, Where=self.schema.FOO.BAR == 12).toSQL(),
+ SQLFragment("delete from FOO where BAR = ?", [12])
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><del>- Delete(self.schema.FOO,
- Where=None).toSQL(),
</del><ins>+ Delete(self.schema.FOO, Where=None).toSQL(),
</ins><span class="cx"> SQLFragment("delete from FOO")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_lock(self):
</span><span class="cx"> """
</span><del>- L{Lock.exclusive} generates a ('lock table') statement, locking the
</del><ins>+ L{Lock.exclusive} generates a C{lock table} statement, locking the
</ins><span class="cx"> table in the specified mode.
</span><span class="cx"> """
</span><del>- self.assertEquals(Lock.exclusive(self.schema.FOO).toSQL(),
- SQLFragment("lock table FOO in exclusive mode"))
</del><ins>+ self.assertEquals(
+ Lock.exclusive(self.schema.FOO).toSQL(),
+ SQLFragment("lock table FOO in exclusive mode")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_databaseLock(self):
</span><span class="cx"> """
</span><del>- L{DatabaseLock} generates a ('pg_advisory_lock') statement
</del><ins>+ L{DatabaseLock} generates a C{pg_advisory_lock} statement
</ins><span class="cx"> """
</span><del>- self.assertEquals(DatabaseLock().toSQL(),
- SQLFragment("select pg_advisory_lock(1)"))
</del><ins>+ self.assertEquals(
+ DatabaseLock().toSQL(),
+ SQLFragment("select pg_advisory_lock(1)")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_databaseUnlock(self):
</span><span class="cx"> """
</span><del>- L{DatabaseUnlock} generates a ('pg_advisory_unlock') statement
</del><ins>+ L{DatabaseUnlock} generates a C{pg_advisory_unlock} statement
</ins><span class="cx"> """
</span><del>- self.assertEquals(DatabaseUnlock().toSQL(),
- SQLFragment("select pg_advisory_unlock(1)"))
</del><ins>+ self.assertEquals(
+ DatabaseUnlock().toSQL(),
+ SQLFragment("select pg_advisory_unlock(1)")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_savepoint(self):
</span><span class="cx"> """
</span><del>- L{Savepoint} generates a ('savepoint') statement.
</del><ins>+ L{Savepoint} generates a C{savepoint} statement.
</ins><span class="cx"> """
</span><del>- self.assertEquals(Savepoint("test").toSQL(),
- SQLFragment("savepoint test"))
</del><ins>+ self.assertEquals(
+ Savepoint("test").toSQL(),
+ SQLFragment("savepoint test")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_rollbacktosavepoint(self):
</span><span class="cx"> """
</span><del>- L{RollbackToSavepoint} generates a ('rollback to savepoint') statement.
</del><ins>+ L{RollbackToSavepoint} generates a C{rollback to savepoint} statement.
</ins><span class="cx"> """
</span><del>- self.assertEquals(RollbackToSavepoint("test").toSQL(),
- SQLFragment("rollback to savepoint test"))
</del><ins>+ self.assertEquals(
+ RollbackToSavepoint("test").toSQL(),
+ SQLFragment("rollback to savepoint test")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_releasesavepoint(self):
</span><span class="cx"> """
</span><del>- L{ReleaseSavepoint} generates a ('release savepoint') statement.
</del><ins>+ L{ReleaseSavepoint} generates a C{release savepoint} statement.
</ins><span class="cx"> """
</span><del>- self.assertEquals(ReleaseSavepoint("test").toSQL(),
- SQLFragment("release savepoint test"))
</del><ins>+ self.assertEquals(
+ ReleaseSavepoint("test").toSQL(),
+ SQLFragment("release savepoint test")
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_savepointaction(self):
</span><span class="cx"> """
</span><del>- L{SavepointAction} generates a ('savepoint') statement.
</del><ins>+ L{SavepointAction} generates a C{savepoint} statement.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(SavepointAction("test")._name, "test")
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_limit(self):
</span><span class="cx"> """
</span><del>- A L{Select} object with a 'Limit' keyword parameter will generate
- a SQL statement with a 'limit' clause.
</del><ins>+ A L{Select} object with a C{Limit} keyword parameter will generate
+ a SQL statement with a C{limit} clause.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR],
- From=self.schema.FOO,
- Limit=123).toSQL(),
- SQLFragment(
- "select BAR from FOO limit ?", [123]))
</del><ins>+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Limit=123
+ ).toSQL(),
+ SQLFragment("select BAR from FOO limit ?", [123])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_limitOracle(self):
</span><span class="cx"> """
</span><del>- A L{Select} object with a 'Limit' keyword parameter will generate a SQL
- statement using a ROWNUM subquery for Oracle.
</del><ins>+ A L{Select} object with a C{Limit} keyword parameter will generate a
+ SQL statement using a ROWNUM subquery for Oracle.
</ins><span class="cx">
</span><span class="cx"> See U{this "ask tom" article from 2006 for more
</span><span class="cx"> information
</span><span class="cx"> <http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html>}.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR],
- From=self.schema.FOO,
- Limit=123).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</del><ins>+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Limit=123
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> "select * from (select BAR from FOO) "
</span><del>- "where ROWNUM <= ?", [123])
</del><ins>+ "where ROWNUM <= ?", [123]
+ )
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_having(self):
</span><span class="cx"> """
</span><del>- A L{Select} object with a 'Having' keyword parameter will generate
- a SQL statement with a 'having' expression.
</del><ins>+ A L{Select} object with a C{Having} keyword parameter will generate
+ a SQL statement with a C{having} expression.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR],
- From=self.schema.FOO,
- Having=Max(self.schema.FOO.BAZ) < 7).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Having=Max(self.schema.FOO.BAZ) < 7
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select BAR from FOO having max(BAZ) < ?", [7])
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_distinct(self):
</span><span class="cx"> """
</span><del>- A L{Select} object with a 'Disinct' keyword parameter with a value of
- C{True} will generate a SQL statement with a 'distinct' keyword
</del><ins>+ A L{Select} object with a C{Disinct} keyword parameter with a value of
+ C{True} will generate a SQL statement with a C{distinct} keyword
</ins><span class="cx"> preceding its list of columns.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Select([self.schema.FOO.BAR], From=self.schema.FOO,
- Distinct=True).toSQL(),
</del><ins>+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Distinct=True
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("select distinct BAR from FOO")
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -1423,25 +1641,26 @@
</span><span class="cx"> def test_nextSequenceValue(self):
</span><span class="cx"> """
</span><span class="cx"> When a sequence is used as a value in an expression, it renders as the
</span><del>- call to 'nextval' that will produce its next value.
</del><ins>+ call to C{nextval} that will produce its next value.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.BOZ.QUX:
- self.schema.A_SEQ}).toSQL(),
- SQLFragment("insert into BOZ (QUX) values (nextval('A_SEQ'))", []))
</del><ins>+ Insert({self.schema.BOZ.QUX: self.schema.A_SEQ}).toSQL(),
+ SQLFragment("insert into BOZ (QUX) values (nextval('A_SEQ'))", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_nextSequenceValueOracle(self):
</span><span class="cx"> """
</span><span class="cx"> When a sequence is used as a value in an expression in the Oracle
</span><del>- dialect, it renders as the 'nextval' attribute of the appropriate
</del><ins>+ dialect, it renders as the C{nextval} attribute of the appropriate
</ins><span class="cx"> sequence.
</span><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.BOZ.QUX:
- self.schema.A_SEQ}).toSQL(
- QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
- SQLFragment("insert into BOZ (QUX) values (A_SEQ.nextval)", []))
</del><ins>+ Insert(
+ {self.schema.BOZ.QUX: self.schema.A_SEQ}
+ ).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
+ SQLFragment("insert into BOZ (QUX) values (A_SEQ.nextval)", [])
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_nextSequenceDefaultImplicitExplicitOracle(self):
</span><span class="lines">@@ -1452,68 +1671,80 @@
</span><span class="cx"> """
</span><span class="cx"> addSQLToSchema(
</span><span class="cx"> schema=self.schema.model,
</span><del>- schemaData="create table DFLTR (a varchar(255), "
- "b integer default nextval('A_SEQ'));"
</del><ins>+ schemaData=(
+ "create table DFLTR (a varchar(255), "
+ "b integer default nextval('A_SEQ'));"
+ )
</ins><span class="cx"> )
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.DFLTR.a: 'hello'}).toSQL(
</del><ins>+ Insert({self.schema.DFLTR.a: "hello"}).toSQL(
</ins><span class="cx"> QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))
</span><span class="cx"> ),
</span><span class="cx"> SQLFragment("insert into DFLTR (a, b) values "
</span><del>- "(?, A_SEQ.nextval)", ['hello']),
</del><ins>+ "(?, A_SEQ.nextval)", ["hello"]),
</ins><span class="cx"> )
</span><span class="cx"> # Should be the same if it's explicitly specified.
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({self.schema.DFLTR.a: 'hello',
- self.schema.DFLTR.b: self.schema.A_SEQ}).toSQL(
</del><ins>+ Insert(
+ {
+ self.schema.DFLTR.a: "hello",
+ self.schema.DFLTR.b: self.schema.A_SEQ
+ }
+ ).toSQL(
</ins><span class="cx"> QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))
</span><span class="cx"> ),
</span><del>- SQLFragment("insert into DFLTR (a, b) values "
- "(?, A_SEQ.nextval)", ['hello']),
</del><ins>+ SQLFragment(
+ "insert into DFLTR (a, b) values (?, A_SEQ.nextval)", ["hello"]
+ ),
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_numericParams(self):
</span><span class="cx"> """
</span><del>- An L{IAsyncTransaction} with the 'numeric' paramstyle attribute will
- cause statements to be generated with parameters in the style of :1 :2
- :3, as per the DB-API.
</del><ins>+ An L{IAsyncTransaction} with the C{numeric} paramstyle attribute will
+ cause statements to be generated with parameters in the style of
+ C{:1 :2 :3}, as per the DB-API.
</ins><span class="cx"> """
</span><span class="cx"> stmts = []
</span><ins>+
</ins><span class="cx"> class FakeOracleTxn(object):
</span><span class="cx"> def execSQL(self, text, params, exc):
</span><span class="cx"> stmts.append((text, params))
</span><span class="cx"> dialect = ORACLE_DIALECT
</span><del>- paramstyle = 'numeric'
- Select([self.schema.FOO.BAR],
- From=self.schema.FOO,
- Where=(self.schema.FOO.BAR == 7).And(
- self.schema.FOO.BAZ == 9)
- ).on(FakeOracleTxn())
</del><ins>+ paramstyle = "numeric"
+
+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Where=(self.schema.FOO.BAR == 7).And(self.schema.FOO.BAZ == 9)
+ ).on(FakeOracleTxn())
+
</ins><span class="cx"> self.assertEquals(
</span><del>- stmts, [("select BAR from FOO where BAR = :1 and BAZ = :2",
- [7, 9])]
</del><ins>+ stmts,
+ [("select BAR from FOO where BAR = :1 and BAZ = :2", [7, 9])]
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_rewriteOracleNULLs_Select(self):
</span><span class="cx"> """
</span><span class="cx"> Oracle databases cannot distinguish between the empty string and
</span><del>- C{NULL}. When you insert an empty string, C{cx_Oracle} therefore treats
- it as a C{None} and will return that when you select it back again. We
- address this in the schema by dropping 'not null' constraints.
</del><ins>+ C{NULL}. When you insert an empty string, C{cx_Oracle} therefore
+ treats it as a C{None} and will return that when you select it back
+ again. We address this in the schema by dropping C{not null}
+ constraints.
</ins><span class="cx">
</span><span class="cx"> Therefore, when executing a statement which includes a string column,
</span><del>- 'on' should rewrite None return values from C{cx_Oracle} to be empty
</del><ins>+ C{on} should rewrite None return values from C{cx_Oracle} to be empty
</ins><span class="cx"> bytestrings, but only for string columns.
</span><span class="cx"> """
</span><del>-
</del><span class="cx"> rows = resultOf(
</span><del>- Select([self.schema.NULLCHECK.ASTRING,
- self.schema.NULLCHECK.ANUMBER],
- From=self.schema.NULLCHECK).on(NullTestingOracleTxn()))[0]
</del><ins>+ Select(
+ [self.schema.NULLCHECK.ASTRING, self.schema.NULLCHECK.ANUMBER],
+ From=self.schema.NULLCHECK
+ ).on(NullTestingOracleTxn())
+ )[0]
</ins><span class="cx">
</span><del>- self.assertEquals(rows, [['', None]])
</del><ins>+ self.assertEquals(rows, [["", None]])
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_rewriteOracleNULLs_SelectAllColumns(self):
</span><span class="lines">@@ -1524,56 +1755,92 @@
</span><span class="cx"> rows = resultOf(
</span><span class="cx"> Select(From=self.schema.NULLCHECK).on(NullTestingOracleTxn())
</span><span class="cx"> )[0]
</span><del>- self.assertEquals(rows, [['', None]])
</del><ins>+ self.assertEquals(rows, [["", None]])
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_nestedLogicalExpressions(self):
</span><span class="cx"> """
</span><span class="cx"> Make sure that logical operator precedence inserts proper parenthesis
</span><del>- when needed. e.g. 'a.And(b.Or(c))' needs to be 'a and (b or c)' not 'a
- and b or c'.
</del><ins>+ when needed. e.g. C{a.And(b.Or(c))} needs to be C{a and (b or c)} not
+ C{a and b or c}.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAR != 7).
- And(self.schema.FOO.BAZ != 8).
- And((self.schema.FOO.BAR == 8).Or(self.schema.FOO.BAZ == 0))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAR != 7
+ ).And(
+ self.schema.FOO.BAZ != 8
+ ).And(
+ (self.schema.FOO.BAR == 8).Or(self.schema.FOO.BAZ == 0)
+ )
+ )
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select * from FOO where BAR != ? and BAZ != ? and "
- "(BAR = ? or BAZ = ?)", [7, 8, 8, 0]))
</del><ins>+ SQLFragment(
+ "select * from FOO where BAR != ? and BAZ != ? and "
+ "(BAR = ? or BAZ = ?)",
+ [7, 8, 8, 0]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAR != 7).
- Or(self.schema.FOO.BAZ != 8).
- Or((self.schema.FOO.BAR == 8).And(self.schema.FOO.BAZ == 0))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAR != 7
+ ).Or(
+ self.schema.FOO.BAZ != 8
+ ).Or(
+ (
+ self.schema.FOO.BAR == 8
+ ).And(
+ self.schema.FOO.BAZ == 0
+ )
+ )
+ )
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select * from FOO where BAR != ? or BAZ != ? or "
- "BAR = ? and BAZ = ?", [7, 8, 8, 0]))
</del><ins>+ SQLFragment(
+ "select * from FOO where BAR != ? or BAZ != ? or "
+ "BAR = ? and BAZ = ?",
+ [7, 8, 8, 0]
+ )
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Select(
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(self.schema.FOO.BAR != 7).
- Or(self.schema.FOO.BAZ != 8).
- And((self.schema.FOO.BAR == 8).Or(self.schema.FOO.BAZ == 0))
</del><ins>+ Where=(
+ (
+ self.schema.FOO.BAR != 7
+ ).Or(
+ self.schema.FOO.BAZ != 8
+ ).And(
+ (self.schema.FOO.BAR == 8).Or(self.schema.FOO.BAZ == 0)
+ )
+ )
</ins><span class="cx"> ).toSQL(),
</span><del>- SQLFragment("select * from FOO where (BAR != ? or BAZ != ?) and "
- "(BAR = ? or BAZ = ?)", [7, 8, 8, 0]))
</del><ins>+ SQLFragment(
+ "select * from FOO where (BAR != ? or BAZ != ?) and "
+ "(BAR = ? or BAZ = ?)",
+ [7, 8, 8, 0]
+ )
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_updateWithNULL(self):
</span><span class="cx"> """
</span><del>- As per the DB-API specification, "SQL NULL values are represented by the
- Python None singleton on input and output." When a C{None} is provided
- as a value to an L{Update}, it will be relayed to the database as a
- parameter.
</del><ins>+ As per the DB-API specification, "SQL NULL values are represented by
+ the Python None singleton on input and output." When a C{None} is
+ provided as a value to an L{Update}, it will be relayed to the database
+ as a parameter.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><del>- Update({self.schema.BOZ.QUX: None},
- Where=self.schema.BOZ.QUX == 7).toSQL(),
</del><ins>+ Update(
+ {self.schema.BOZ.QUX: None},
+ Where=self.schema.BOZ.QUX == 7
+ ).toSQL(),
</ins><span class="cx"> SQLFragment("update BOZ set QUX = ? where QUX = ?", [None, 7])
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -1581,20 +1848,27 @@
</span><span class="cx"> def test_subSelectComparison(self):
</span><span class="cx"> """
</span><span class="cx"> A comparison of a column to a sub-select in a where clause will result
</span><del>- in a parenthetical 'Where' clause.
</del><ins>+ in a parenthetical C{where} clause.
</ins><span class="cx"> """
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Update(
</span><span class="cx"> {self.schema.BOZ.QUX: 9},
</span><del>- Where=self.schema.BOZ.QUX ==
- Select([self.schema.FOO.BAR], From=self.schema.FOO,
- Where=self.schema.FOO.BAZ == 12)).toSQL(),
</del><ins>+ Where=(
+ self.schema.BOZ.QUX ==
+ Select(
+ [self.schema.FOO.BAR],
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAZ == 12
+ )
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> # NOTE: it's very important that the comparison _always_ go in
</span><del>- # this order (column from the UPDATE first, inner SELECT second)
- # as the other order will be considered a syntax error.
- "update BOZ set QUX = ? where QUX = ("
- "select BAR from FOO where BAZ = ?)", [9, 12]
</del><ins>+ # this order (column from the UPDATE first, inner SELECT
+ # second) as the other order will be considered a syntax error.
+ "update BOZ set QUX = ? "
+ "where QUX = (select BAR from FOO where BAZ = ?)",
+ [9, 12]
</ins><span class="cx"> )
</span><span class="cx"> )
</span><span class="cx">
</span><span class="lines">@@ -1610,10 +1884,15 @@
</span><span class="cx"> self.assertEquals(
</span><span class="cx"> Update(
</span><span class="cx"> {self.schema.BOZ.QUX: 1},
</span><del>- Where=(self.schema.BOZ.QUX, self.schema.BOZ.QUUX) ==
- Select([self.schema.FOO.BAR, self.schema.FOO.BAZ],
- From=self.schema.FOO,
- Where=self.schema.FOO.BAZ == 2)).toSQL(),
</del><ins>+ Where=(
+ (self.schema.BOZ.QUX, self.schema.BOZ.QUUX) ==
+ Select(
+ [self.schema.FOO.BAR, self.schema.FOO.BAZ],
+ From=self.schema.FOO,
+ Where=self.schema.FOO.BAZ == 2
+ )
+ )
+ ).toSQL(),
</ins><span class="cx"> SQLFragment(
</span><span class="cx"> # NOTE: it's very important that the comparison _always_ go in
</span><span class="cx"> # this order (tuple of columns from the UPDATE first, inner
</span><span class="lines">@@ -1633,8 +1912,10 @@
</span><span class="cx"> Select(
</span><span class="cx"> [self.schema.FOO.BAR],
</span><span class="cx"> From=self.schema.FOO,
</span><del>- Where=(Tuple([self.schema.FOO.BAR, self.schema.FOO.BAZ]) ==
- Tuple([Constant(7), Constant(9)]))
</del><ins>+ Where=(
+ Tuple([self.schema.FOO.BAR, self.schema.FOO.BAZ]) ==
+ Tuple([Constant(7), Constant(9)])
+ )
</ins><span class="cx"> ).toSQL(),
</span><span class="cx"> SQLFragment(
</span><span class="cx"> "select BAR from FOO where (BAR, BAZ) = ((?, ?))", [7, 9]
</span><span class="lines">@@ -1644,12 +1925,11 @@
</span><span class="cx">
</span><span class="cx"> def test_oracleTableTruncation(self):
</span><span class="cx"> """
</span><del>- L{Table}'s SQL generation logic will truncate table names if the dialect
- (i.e. Oracle) demands it. (See txdav.common.datastore.sql_tables for
- the schema translator and enforcement of name uniqueness in the derived
- schema.)
</del><ins>+ L{Table}'s SQL generation logic will truncate table names if the
+ dialect (i.e. Oracle) demands it.
+ (See txdav.common.datastore.sql_tables for the schema translator and
+ enforcement of name uniqueness in the derived schema.)
</ins><span class="cx"> """
</span><del>-
</del><span class="cx"> addSQLToSchema(
</span><span class="cx"> self.schema.model,
</span><span class="cx"> "create table veryveryveryveryveryveryveryverylong "
</span><span class="lines">@@ -1657,18 +1937,20 @@
</span><span class="cx"> )
</span><span class="cx"> vvl = self.schema.veryveryveryveryveryveryveryverylong
</span><span class="cx"> self.assertEquals(
</span><del>- Insert({vvl.foo: 1}).toSQL(QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))),
</del><ins>+ Insert({vvl.foo: 1}).toSQL(
+ QueryGenerator(ORACLE_DIALECT, FixedPlaceholder("?"))
+ ),
</ins><span class="cx"> SQLFragment(
</span><del>- "insert into veryveryveryveryveryveryveryve (foo) values "
- "(?)", [1]
</del><ins>+ "insert into veryveryveryveryveryveryveryve (foo) values (?)",
+ [1]
</ins><span class="cx"> )
</span><span class="cx"> )
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_columnEqualityTruth(self):
</span><span class="cx"> """
</span><del>- Mostly in support of test_columnsAsDictKeys, the 'same' column should
- compare True to itself and False to other values.
</del><ins>+ Mostly in support of L{test_columnsAsDictKeys}, the "same" column
+ should compare C{True} to itself and C{False} to other values.
</ins><span class="cx"> """
</span><span class="cx"> s = self.schema
</span><span class="cx"> self.assertEquals(bool(s.FOO.BAR == s.FOO.BAR), True)
</span><span class="lines">@@ -1679,10 +1961,10 @@
</span><span class="cx"> def test_columnsAsDictKeys(self):
</span><span class="cx"> """
</span><span class="cx"> An odd corner of the syntactic sugar provided by the DAL is that the
</span><del>- column objects have to participate both in augmented equality comparison
- ("==" returns an expression object) as well as dictionary keys (for
- Insert and Update statement objects). Therefore it should be possible
- to I{manipulate} dictionaries of keys as well.
</del><ins>+ column objects have to participate both in augmented equality
+ comparison (C{==} returns an expression object) as well as dictionary
+ keys (for Insert and Update statement objects). Therefore it should be
+ possible to I{manipulate} dictionaries of keys as well.
</ins><span class="cx"> """
</span><span class="cx"> values = {self.schema.FOO.BAR: 1}
</span><span class="cx"> self.assertEquals(values, {self.schema.FOO.BAR: 1})
</span><span class="lines">@@ -1695,31 +1977,38 @@
</span><span class="cx"> def test_rewriteOracleNULLs_Insert(self):
</span><span class="cx"> """
</span><span class="cx"> The behavior described in L{test_rewriteOracleNULLs_Select} applies to
</span><del>- other statement types as well, specifically those with 'returning'
</del><ins>+ other statement types as well, specifically those with C{returning}
</ins><span class="cx"> clauses.
</span><span class="cx"> """
</span><span class="cx"> # Add 2 cursor variable values so that these will be used by
</span><span class="cx"> # FakeVariable.getvalue.
</span><span class="cx"> self.factory.varvals.extend([None, None])
</span><span class="cx"> rows = self.resultOf(
</span><del>- Insert({self.schema.NULLCHECK.ASTRING: '',
- self.schema.NULLCHECK.ANUMBER: None},
- Return=[self.schema.NULLCHECK.ASTRING,
- self.schema.NULLCHECK.ANUMBER]
- ).on(self.createTransaction()))[0]
- self.assertEquals(rows, [['', None]])
</del><ins>+ Insert(
+ {
+ self.schema.NULLCHECK.ASTRING: "",
+ self.schema.NULLCHECK.ANUMBER: None,
+ },
+ Return=[
+ self.schema.NULLCHECK.ASTRING,
+ self.schema.NULLCHECK.ANUMBER,
+ ]
+ ).on(self.createTransaction())
+ )[0]
+ self.assertEquals(rows, [["", None]])
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_insertMultiReturnOnOracleTxn(self):
</span><span class="cx"> """
</span><span class="cx"> As described in L{test_insertMultiReturnOracle}, Oracle deals with
</span><del>- 'returning' clauses by using out parameters. However, this is not quite
- enough, as the code needs to actually retrieve the values from the out
- parameters.
</del><ins>+ C{returning} clauses by using out parameters. However, this is not
+ quite enough, as the code needs to actually retrieve the values from
+ the out parameters.
</ins><span class="cx"> """
</span><del>- i = Insert({self.schema.FOO.BAR: 40,
- self.schema.FOO.BAZ: 50},
- Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ))
</del><ins>+ i = Insert(
+ {self.schema.FOO.BAR: 40, self.schema.FOO.BAZ: 50},
+ Return=(self.schema.FOO.BAR, self.schema.FOO.BAZ)
+ )
</ins><span class="cx"> self.factory.varvals.extend(["first val!", "second val!"])
</span><span class="cx"> result = self.resultOf(i.on(self.createTransaction()))
</span><span class="cx"> self.assertEquals(result, [[["first val!", "second val!"]]])
</span><span class="lines">@@ -1737,15 +2026,18 @@
</span><span class="cx"> """
</span><span class="cx"> # This statement should return nothing from .fetchall(), so...
</span><span class="cx"> self.factory.hasResults = False
</span><del>- i = Insert({self.schema.FOO.BAR: 40,
- self.schema.FOO.BAZ: 50})
</del><ins>+ i = Insert(
+ {self.schema.FOO.BAR: 40, self.schema.FOO.BAZ: 50}
+ )
</ins><span class="cx"> result = self.resultOf(i.on(self.createTransaction()))
</span><span class="cx"> self.assertEquals(result, [None])
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-class OracleConnectionTests(ConnectionPoolHelper, ExampleSchemaHelper,
- OracleConnectionMethods, TestCase):
</del><ins>+class OracleConnectionTests(
+ ConnectionPoolHelper, ExampleSchemaHelper, OracleConnectionMethods,
+ TestCase
+):
</ins><span class="cx"> """
</span><span class="cx"> Tests which use an oracle connection.
</span><span class="cx"> """
</span><span class="lines">@@ -1754,22 +2046,24 @@
</span><span class="cx">
</span><span class="cx"> def setUp(self):
</span><span class="cx"> """
</span><del>- Create a fake oracle-ish connection pool without using real threads or a
- real database.
</del><ins>+ Create a fake oracle-ish connection pool without using real threads or
+ a real database.
</ins><span class="cx"> """
</span><del>- self.patch(syntax, 'cx_Oracle', FakeCXOracleModule)
</del><ins>+ self.patch(syntax, "cx_Oracle", FakeCXOracleModule)
</ins><span class="cx"> super(OracleConnectionTests, self).setUp()
</span><span class="cx"> ExampleSchemaHelper.setUp(self)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-class OracleNetConnectionTests(NetworkedPoolHelper, ExampleSchemaHelper,
- OracleConnectionMethods, TestCase):
</del><ins>+class OracleNetConnectionTests(
+ NetworkedPoolHelper, ExampleSchemaHelper, OracleConnectionMethods,
+ TestCase
+):
</ins><span class="cx">
</span><span class="cx"> dialect = ORACLE_DIALECT
</span><span class="cx">
</span><span class="cx"> def setUp(self):
</span><del>- self.patch(syntax, 'cx_Oracle', FakeCXOracleModule)
</del><ins>+ self.patch(syntax, "cx_Oracle", FakeCXOracleModule)
</ins><span class="cx"> super(OracleNetConnectionTests, self).setUp()
</span><span class="cx"> ExampleSchemaHelper.setUp(self)
</span><span class="cx"> self.pump.client.dialect = ORACLE_DIALECT
</span></span></pre></div>
<a id="twexttrunktwextenterprisefixturespy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/fixtures.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/fixtures.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/fixtures.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> from twext.internet.threadutils import ThreadHolder
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> def buildConnectionPool(testCase, schemaText="", dialect=SQLITE_DIALECT):
</span><span class="cx"> """
</span><span class="cx"> Build a L{ConnectionPool} for testing purposes, with the given C{testCase}.
</span><span class="lines">@@ -56,17 +57,21 @@
</span><span class="cx"> """
</span><span class="cx"> sqlitename = testCase.mktemp()
</span><span class="cx"> seqs = {}
</span><ins>+
</ins><span class="cx"> def connectionFactory(label=testCase.id()):
</span><span class="cx"> conn = sqlite3.connect(sqlitename)
</span><ins>+
</ins><span class="cx"> def nextval(seq):
</span><span class="cx"> result = seqs[seq] = seqs.get(seq, 0) + 1
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> conn.create_function("nextval", 1, nextval)
</span><span class="cx"> return conn
</span><ins>+
</ins><span class="cx"> con = connectionFactory()
</span><span class="cx"> con.executescript(schemaText)
</span><span class="cx"> con.commit()
</span><del>- pool = ConnectionPool(connectionFactory, paramstyle='numeric',
</del><ins>+ pool = ConnectionPool(connectionFactory, paramstyle="numeric",
</ins><span class="cx"> dialect=SQLITE_DIALECT)
</span><span class="cx"> pool.startService()
</span><span class="cx"> testCase.addCleanup(pool.stopService)
</span><span class="lines">@@ -77,16 +82,18 @@
</span><span class="cx"> def resultOf(deferred, propagate=False):
</span><span class="cx"> """
</span><span class="cx"> Add a callback and errback which will capture the result of a L{Deferred}
</span><del>- in a list, and return that list. If 'propagate' is True, pass through the
</del><ins>+ in a list, and return that list. If C{propagate} is True, pass through the
</ins><span class="cx"> results.
</span><span class="cx"> """
</span><span class="cx"> results = []
</span><ins>+
</ins><span class="cx"> if propagate:
</span><span class="cx"> def cb(r):
</span><span class="cx"> results.append(r)
</span><span class="cx"> return r
</span><span class="cx"> else:
</span><span class="cx"> cb = results.append
</span><ins>+
</ins><span class="cx"> deferred.addBoth(cb)
</span><span class="cx"> return results
</span><span class="cx">
</span><span class="lines">@@ -128,12 +135,15 @@
</span><span class="cx"> oget = newq.get
</span><span class="cx"> newq.get = lambda: oget(timeout=0)
</span><span class="cx"> oput = newq.put
</span><ins>+
</ins><span class="cx"> def putit(x):
</span><span class="cx"> p = oput(x)
</span><span class="cx"> if not self.test.paused:
</span><span class="cx"> self.flush()
</span><span class="cx"> return p
</span><ins>+
</ins><span class="cx"> newq.put = putit
</span><ins>+
</ins><span class="cx"> self._q_ = newq
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -184,7 +194,7 @@
</span><span class="cx">
</span><span class="cx"> def suggestThreadPoolSize(self, size):
</span><span class="cx"> """
</span><del>- Approximate the behavior of a 'real' reactor.
</del><ins>+ Approximate the behavior of a "real" reactor.
</ins><span class="cx"> """
</span><span class="cx"> self._pool.adjustPoolsize(maxthreads=size)
</span><span class="cx">
</span><span class="lines">@@ -314,8 +324,10 @@
</span><span class="cx">
</span><span class="cx"> def synchronousConnectionFactory(test):
</span><span class="cx"> tmpdb = test.mktemp()
</span><ins>+
</ins><span class="cx"> def connect():
</span><span class="cx"> return sqlite3.connect(tmpdb)
</span><ins>+
</ins><span class="cx"> return connect
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -561,8 +573,10 @@
</span><span class="cx"> @rtype: L{FakeConnection}
</span><span class="cx"> """
</span><span class="cx"> aConnection = FakeConnection(self)
</span><ins>+
</ins><span class="cx"> def thunk():
</span><span class="cx"> return aConnection
</span><ins>+
</ins><span class="cx"> self._connectResultQueue.append(thunk)
</span><span class="cx"> return aConnection
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterpriseienterprisepy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/ienterprise.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/ienterprise.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/ienterprise.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -50,9 +50,9 @@
</span><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><del>-POSTGRES_DIALECT = 'postgres-dialect'
-ORACLE_DIALECT = 'oracle-dialect'
-SQLITE_DIALECT = 'sqlite-dialect'
</del><ins>+POSTGRES_DIALECT = "postgres-dialect"
+ORACLE_DIALECT = "oracle-dialect"
+SQLITE_DIALECT = "sqlite-dialect"
</ins><span class="cx"> ORACLE_TABLE_NAME_MAX = 30
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -64,14 +64,16 @@
</span><span class="cx">
</span><span class="cx"> paramstyle = Attribute(
</span><span class="cx"> """
</span><del>- A copy of the 'paramstyle' attribute from a DB-API 2.0 module.
- """)
</del><ins>+ A copy of the C{paramstyle} attribute from a DB-API 2.0 module.
+ """
+ )
</ins><span class="cx">
</span><span class="cx"> dialect = Attribute(
</span><span class="cx"> """
</span><del>- A copy of the 'dialect' attribute from the connection pool. One of the
- C{*_DIALECT} constants in this module, such as C{POSTGRES_DIALECT}.
- """)
</del><ins>+ A copy of the C{dialect} attribute from the connection pool. One of
+ the C{*_DIALECT} constants in this module, such as L{POSTGRES_DIALECT}.
+ """
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def execSQL(sql, args=(), raiseOnZeroRowCount=None):
</span></span></pre></div>
<a id="twexttrunktwextenterpriselockingpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/locking.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/locking.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/locking.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">
</span><span class="cx"> @return: inSchema
</span><span class="cx"> """
</span><del>- LockTable = Table(inSchema, 'NAMED_LOCK')
</del><ins>+ LockTable = Table(inSchema, "NAMED_LOCK")
</ins><span class="cx">
</span><span class="cx"> LockTable.addColumn("LOCK_NAME", SQLType("varchar", 255))
</span><span class="cx"> LockTable.tableConstraint(Constraint.NOT_NULL, ["LOCK_NAME"])
</span><span class="lines">@@ -85,11 +85,16 @@
</span><span class="cx"> def autoRelease(self):
</span><span class="cx"> txn.preCommit(lambda: self.release(True))
</span><span class="cx"> return self
</span><ins>+
</ins><span class="cx"> def lockFailed(f):
</span><span class="cx"> raise LockTimeout(name)
</span><del>- return cls.create(txn, lockName=name).addCallback(autoRelease).addErrback(lockFailed)
</del><span class="cx">
</span><ins>+ d = cls.create(txn, lockName=name)
+ d.addCallback(autoRelease)
+ d.addErrback(lockFailed)
+ return d
</ins><span class="cx">
</span><ins>+
</ins><span class="cx"> def release(self, ignoreAlreadyUnlocked=False):
</span><span class="cx"> """
</span><span class="cx"> Release this lock.
</span></span></pre></div>
<a id="twexttrunktwextenterprisequeuepy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/queue.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/queue.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/queue.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx"> (in the worst case) pass from worker->controller->controller->worker.
</span><span class="cx"> """
</span><span class="cx">
</span><del>- def performWork(table, workID): #@NoSelf
</del><ins>+ def performWork(table, workID):
</ins><span class="cx"> """
</span><span class="cx"> @param table: The table where work is waiting.
</span><span class="cx"> @type table: L{TableSyntax}
</span><span class="lines">@@ -142,7 +142,7 @@
</span><span class="cx"> # Initializing this duplicate schema avoids a circular dependency, but this
</span><span class="cx"> # should really be accomplished with independent schema objects that the
</span><span class="cx"> # transaction is made aware of somehow.
</span><del>- NodeTable = Table(inSchema, 'NODE_INFO')
</del><ins>+ NodeTable = Table(inSchema, "NODE_INFO")
</ins><span class="cx">
</span><span class="cx"> NodeTable.addColumn("HOSTNAME", SQLType("varchar", 255))
</span><span class="cx"> NodeTable.addColumn("PID", SQLType("integer", None))
</span><span class="lines">@@ -151,12 +151,14 @@
</span><span class="cx"> # Note: in the real data structure, this is actually a not-cleaned-up
</span><span class="cx"> # sqlparse internal data structure, but it *should* look closer to
</span><span class="cx"> # this.
</span><del>- ProcedureCall("timezone", ["UTC", NamedValue('CURRENT_TIMESTAMP')])
</del><ins>+ ProcedureCall("timezone", ["UTC", NamedValue("CURRENT_TIMESTAMP")])
</ins><span class="cx"> )
</span><span class="cx"> for column in NodeTable.columns:
</span><span class="cx"> NodeTable.tableConstraint(Constraint.NOT_NULL, [column.name])
</span><del>- NodeTable.primaryKey = [NodeTable.columnNamed("HOSTNAME"),
- NodeTable.columnNamed("PORT")]
</del><ins>+ NodeTable.primaryKey = [
+ NodeTable.columnNamed("HOSTNAME"),
+ NodeTable.columnNamed("PORT"),
+ ]
</ins><span class="cx">
</span><span class="cx"> return inSchema
</span><span class="cx">
</span><span class="lines">@@ -260,8 +262,9 @@
</span><span class="cx"> @classmethod
</span><span class="cx"> @wraps(thunk)
</span><span class="cx"> def inner(cls, *a, **k):
</span><del>- raise NotImplementedError(qual(cls) + " does not implement " +
- thunk.func_name)
</del><ins>+ raise NotImplementedError(
+ qual(cls) + " does not implement " + thunk.func_name
+ )
</ins><span class="cx"> return inner
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -360,6 +363,7 @@
</span><span class="cx">
</span><span class="cx"> group = None
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @abstract
</span><span class="cx"> def doWork(self):
</span><span class="cx"> """
</span><span class="lines">@@ -371,6 +375,7 @@
</span><span class="cx"> will be taken care of by the job queueing machinery.
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> @classmethod
</span><span class="cx"> def forTable(cls, table):
</span><span class="cx"> """
</span><span class="lines">@@ -457,8 +462,8 @@
</span><span class="cx">
</span><span class="cx"> class ConnectionFromPeerNode(SchemaAMP):
</span><span class="cx"> """
</span><del>- A connection to a peer node. Symmetric; since the 'client' and the
- 'server' both serve the same role, the logic is the same in every node.
</del><ins>+ A connection to a peer node. Symmetric; since the "client" and the
+ "server" both serve the same role, the logic is the same in every node.
</ins><span class="cx">
</span><span class="cx"> @ivar localWorkerPool: the pool of local worker procesess that can process
</span><span class="cx"> queue work.
</span><span class="lines">@@ -492,8 +497,9 @@
</span><span class="cx"> self.peerPool = peerPool
</span><span class="cx"> self._bonusLoad = 0
</span><span class="cx"> self._reportedLoad = 0
</span><del>- super(ConnectionFromPeerNode, self).__init__(peerPool.schema,
- boxReceiver, locator)
</del><ins>+ super(ConnectionFromPeerNode, self).__init__(
+ peerPool.schema, boxReceiver, locator
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def reportCurrentLoad(self):
</span><span class="lines">@@ -553,13 +559,16 @@
</span><span class="cx"> """
</span><span class="cx"> d = self.callRemote(PerformWork, table=table, workID=workID)
</span><span class="cx"> self._bonusLoad += 1
</span><ins>+
</ins><span class="cx"> @d.addBoth
</span><span class="cx"> def performed(result):
</span><span class="cx"> self._bonusLoad -= 1
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> @d.addCallback
</span><span class="cx"> def success(result):
</span><span class="cx"> return None
</span><ins>+
</ins><span class="cx"> return d
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -577,9 +586,9 @@
</span><span class="cx">
</span><span class="cx"> @return: a L{Deferred} that fires when the work has been completed.
</span><span class="cx"> """
</span><del>- return self.peerPool.performWorkForPeer(table, workID).addCallback(
- lambda ignored: {}
- )
</del><ins>+ d = self.peerPool.performWorkForPeer(table, workID)
+ d.addCallback(lambda ignored: {})
+ return d
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> @IdentifyNode.responder
</span><span class="lines">@@ -720,10 +729,12 @@
</span><span class="cx"> """
</span><span class="cx"> d = self.callRemote(PerformWork, table=table, workID=workID)
</span><span class="cx"> self._load += 1
</span><ins>+
</ins><span class="cx"> @d.addBoth
</span><span class="cx"> def f(result):
</span><span class="cx"> self._load -= 1
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> return d
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -800,8 +811,9 @@
</span><span class="cx"> process has instructed this worker to do it; so, look up the data in
</span><span class="cx"> the row, and do it.
</span><span class="cx"> """
</span><del>- return (ultimatelyPerform(self.transactionFactory, table, workID)
- .addCallback(lambda ignored: {}))
</del><ins>+ d = ultimatelyPerform(self.transactionFactory, table, workID)
+ d.addCallback(lambda ignored: {})
+ return d
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -839,6 +851,7 @@
</span><span class="cx"> except NoSuchRecord:
</span><span class="cx"> # The record has already been removed
</span><span class="cx"> pass
</span><ins>+
</ins><span class="cx"> return inTransaction(txnFactory, work)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -948,30 +961,41 @@
</span><span class="cx"> commit, and asking the local node controller process to do the work.
</span><span class="cx"> """
</span><span class="cx"> created = self.workItemType.create(self.txn, **self.kw)
</span><ins>+
</ins><span class="cx"> def whenCreated(item):
</span><span class="cx"> self._whenProposed.callback(self)
</span><ins>+
</ins><span class="cx"> @self.txn.postCommit
</span><span class="cx"> def whenDone():
</span><span class="cx"> self._whenCommitted.callback(self)
</span><ins>+
</ins><span class="cx"> def maybeLater():
</span><span class="cx"> performer = self._chooser.choosePerformer()
</span><del>- @passthru(performer.performWork(item.table, item.workID)
- .addCallback)
</del><ins>+
+ @passthru(
+ performer.performWork(item.table, item.workID)
+ .addCallback
+ )
</ins><span class="cx"> def performed(result):
</span><span class="cx"> self._whenExecuted.callback(self)
</span><ins>+
</ins><span class="cx"> @performed.addErrback
</span><span class="cx"> def notPerformed(why):
</span><span class="cx"> self._whenExecuted.errback(why)
</span><ins>+
</ins><span class="cx"> reactor = self._chooser.reactor
</span><span class="cx"> when = max(0, astimestamp(item.notBefore) - reactor.seconds())
</span><span class="cx"> # TODO: Track the returned DelayedCall so it can be stopped
</span><span class="cx"> # when the service stops.
</span><span class="cx"> self._chooser.reactor.callLater(when, maybeLater)
</span><ins>+
</ins><span class="cx"> @self.txn.postAbort
</span><span class="cx"> def whenFailed():
</span><span class="cx"> self._whenCommitted.errback(TransactionFailed)
</span><ins>+
</ins><span class="cx"> def whenNotCreated(failure):
</span><span class="cx"> self._whenProposed.errback(failure)
</span><ins>+
</ins><span class="cx"> created.addCallbacks(whenCreated, whenNotCreated)
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1192,6 +1216,7 @@
</span><span class="cx"> """
</span><span class="cx"> if self.workerPool.hasAvailableCapacity():
</span><span class="cx"> return self.workerPool
</span><ins>+
</ins><span class="cx"> if self.peers and not onlyLocally:
</span><span class="cx"> return sorted(self.peers, lambda p: p.currentLoadEstimate())[0]
</span><span class="cx"> else:
</span><span class="lines">@@ -1271,6 +1296,7 @@
</span><span class="cx"> self._lastSeenNodeIndex = nodes.index(
</span><span class="cx"> (self.thisProcess.hostname, self.thisProcess.port)
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> for itemType in self.allWorkItemTypes():
</span><span class="cx"> tooLate = datetime.utcfromtimestamp(
</span><span class="cx"> self.reactor.seconds() - self.queueProcessTimeout
</span><span class="lines">@@ -1282,6 +1308,7 @@
</span><span class="cx"> peer = self.choosePerformer()
</span><span class="cx"> yield peer.performWork(overdueItem.table,
</span><span class="cx"> overdueItem.workID)
</span><ins>+
</ins><span class="cx"> return inTransaction(self.transactionFactory, workCheck)
</span><span class="cx">
</span><span class="cx"> _currentWorkDeferred = None
</span><span class="lines">@@ -1294,8 +1321,10 @@
</span><span class="cx"> those checks in time based on the size of the cluster.
</span><span class="cx"> """
</span><span class="cx"> self._lostWorkCheckCall = None
</span><del>- @passthru(self._periodicLostWorkCheck().addErrback(log.err)
- .addCallback)
</del><ins>+
+ @passthru(
+ self._periodicLostWorkCheck().addErrback(log.err).addCallback
+ )
</ins><span class="cx"> def scheduleNext(result):
</span><span class="cx"> self._currentWorkDeferred = None
</span><span class="cx"> if not self.running:
</span><span class="lines">@@ -1310,6 +1339,7 @@
</span><span class="cx"> self._lostWorkCheckCall = self.reactor.callLater(
</span><span class="cx"> delay, self._lostWorkCheckLoop
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> self._currentWorkDeferred = scheduleNext
</span><span class="cx">
</span><span class="cx">
</span><span class="lines">@@ -1340,10 +1370,12 @@
</span><span class="cx"> txn, hostname=self.hostname, port=self.ampPort,
</span><span class="cx"> pid=self.pid, time=datetime.now()
</span><span class="cx"> )
</span><ins>+
</ins><span class="cx"> for node in nodes:
</span><span class="cx"> self._startConnectingTo(node)
</span><span class="cx">
</span><span class="cx"> self._startingUp = inTransaction(self.transactionFactory, startup)
</span><ins>+
</ins><span class="cx"> @self._startingUp.addBoth
</span><span class="cx"> def done(result):
</span><span class="cx"> self._startingUp = None
</span><span class="lines">@@ -1358,14 +1390,19 @@
</span><span class="cx"> Stop this service, terminating any incoming or outgoing connections.
</span><span class="cx"> """
</span><span class="cx"> yield super(PeerConnectionPool, self).stopService()
</span><ins>+
</ins><span class="cx"> if self._startingUp is not None:
</span><span class="cx"> yield self._startingUp
</span><ins>+
</ins><span class="cx"> if self._listeningPort is not None:
</span><span class="cx"> yield self._listeningPort.stopListening()
</span><ins>+
</ins><span class="cx"> if self._lostWorkCheckCall is not None:
</span><span class="cx"> self._lostWorkCheckCall.cancel()
</span><ins>+
</ins><span class="cx"> if self._currentWorkDeferred is not None:
</span><span class="cx"> yield self._currentWorkDeferred
</span><ins>+
</ins><span class="cx"> for peer in self.peers:
</span><span class="cx"> peer.transport.abortConnection()
</span><span class="cx">
</span><span class="lines">@@ -1397,16 +1434,21 @@
</span><span class="cx"> @type node: L{NodeInfo}
</span><span class="cx"> """
</span><span class="cx"> connected = node.endpoint(self.reactor).connect(self.peerFactory())
</span><ins>+
</ins><span class="cx"> def whenConnected(proto):
</span><span class="cx"> self.mapPeer(node.hostname, node.port, proto)
</span><del>- proto.callRemote(IdentifyNode,
- host=self.thisProcess.hostname,
- port=self.thisProcess.port).addErrback(
- noted, "identify"
- )
</del><ins>+ proto.callRemote(
+ IdentifyNode,
+ host=self.thisProcess.hostname,
+ port=self.thisProcess.port
+ ).addErrback(noted, "identify")
+
</ins><span class="cx"> def noted(err, x="connect"):
</span><del>- log.msg("Could not {0} to cluster peer {1} because {2}"
- .format(x, node, str(err.value)))
</del><ins>+ log.msg(
+ "Could not {0} to cluster peer {1} because {2}"
+ .format(x, node, str(err.value))
+ )
+
</ins><span class="cx"> connected.addCallbacks(whenConnected, noted)
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterprisetesttest_adbapi2py"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/test/test_adbapi2.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/test/test_adbapi2.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/test/test_adbapi2.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> from twext.enterprise.adbapi2 import _HookableOperation
</span><span class="cx">
</span><span class="cx">
</span><ins>+
</ins><span class="cx"> class TrashCollector(object):
</span><span class="cx"> """
</span><span class="cx"> Test helper for monitoring gc.garbage.
</span><span class="lines">@@ -170,29 +171,29 @@
</span><span class="cx"> [[counter, echo]] = alphaResult[0]
</span><span class="cx">
</span><span class="cx"> b = self.createTransaction()
</span><del>- # 'b' should have opened a connection.
</del><ins>+ # "b" should have opened a connection.
</ins><span class="cx"> self.assertEquals(len(self.factory.connections), 2)
</span><span class="cx"> betaResult = self.resultOf(b.execSQL("beta"))
</span><span class="cx"> [[bcounter, becho]] = betaResult[0]
</span><span class="cx">
</span><del>- # both 'a' and 'b' are holding open a connection now; let's try to open
</del><ins>+ # both "a" and "b" are holding open a connection now; let's try to open
</ins><span class="cx"> # a third one. (The ordering will be deterministic even if this fails,
</span><span class="cx"> # because those threads are already busy.)
</span><span class="cx"> c = self.createTransaction()
</span><span class="cx"> gammaResult = self.resultOf(c.execSQL("gamma"))
</span><span class="cx">
</span><del>- # Did 'c' open a connection? Let's hope not...
</del><ins>+ # Did "c" open a connection? Let's hope not...
</ins><span class="cx"> self.assertEquals(len(self.factory.connections), 2)
</span><span class="cx"> # SQL shouldn't be executed too soon...
</span><span class="cx"> self.assertEquals(gammaResult, [])
</span><span class="cx">
</span><span class="cx"> commitResult = self.resultOf(b.commit())
</span><span class="cx">
</span><del>- # Now that 'b' has committed, 'c' should be able to complete.
</del><ins>+ # Now that "b" has committed, "c" should be able to complete.
</ins><span class="cx"> [[ccounter, cecho]] = gammaResult[0]
</span><span class="cx">
</span><del>- # The connection for 'a' ought to still be busy, so let's make sure
- # we're using the one for 'c'.
</del><ins>+ # The connection for "a" ought to still be busy, so let's make sure
+ # we're using the one for "c".
</ins><span class="cx"> self.assertEquals(ccounter, bcounter)
</span><span class="cx">
</span><span class="cx"> # Sanity check: the commit should have succeded!
</span><span class="lines">@@ -232,9 +233,11 @@
</span><span class="cx"> self.factory.willFail()
</span><span class="cx"> self.factory.willConnect()
</span><span class="cx"> c = self.createTransaction()
</span><ins>+
</ins><span class="cx"> def checkOneFailure():
</span><span class="cx"> errors = self.flushLoggedErrors(FakeConnectionError)
</span><span class="cx"> self.assertEquals(len(errors), 1)
</span><ins>+
</ins><span class="cx"> checkOneFailure()
</span><span class="cx"> d = c.execSQL("alpha")
</span><span class="cx"> happened = []
</span><span class="lines">@@ -396,17 +399,21 @@
</span><span class="cx"> """
</span><span class="cx"> self.pauseHolders()
</span><span class="cx"> preClose = self.createTransaction()
</span><del>- preCloseResult = self.resultOf(preClose.execSQL('statement'))
</del><ins>+ preCloseResult = self.resultOf(preClose.execSQL("statement"))
</ins><span class="cx"> stopResult = self.resultOf(self.pool.stopService())
</span><span class="cx"> postClose = self.createTransaction()
</span><span class="cx"> queryResult = self.resultOf(postClose.execSQL("hello"))
</span><span class="cx"> self.assertEquals(stopResult, [])
</span><span class="cx"> self.assertEquals(len(queryResult), 1)
</span><del>- self.assertEquals(queryResult[0].type,
- self.translateError(ConnectionError))
</del><ins>+ self.assertEquals(
+ queryResult[0].type,
+ self.translateError(ConnectionError)
+ )
</ins><span class="cx"> self.assertEquals(len(preCloseResult), 1)
</span><del>- self.assertEquals(preCloseResult[0].type,
- self.translateError(ConnectionError))
</del><ins>+ self.assertEquals(
+ preCloseResult[0].type,
+ self.translateError(ConnectionError)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_abortFailsDuringStopService(self):
</span><span class="lines">@@ -454,9 +461,11 @@
</span><span class="cx"> # Use up the available connections ...
</span><span class="cx"> for i in xrange(self.pool.maxConnections):
</span><span class="cx"> active.append(self.createTransaction())
</span><ins>+
</ins><span class="cx"> # ... so that this one has to be spooled.
</span><span class="cx"> spooled = self.createTransaction()
</span><span class="cx"> result = self.resultOf(spooled.execSQL("alpha"))
</span><ins>+
</ins><span class="cx"> # sanity check, it would be bad if this actually executed.
</span><span class="cx"> self.assertEqual(result, [])
</span><span class="cx"> self.resultOf(spooled.abort())
</span><span class="lines">@@ -474,17 +483,21 @@
</span><span class="cx">
</span><span class="cx"> # steal it from the queue so we can do it out of order
</span><span class="cx"> d, work = self.holders[0]._q.get()
</span><ins>+
</ins><span class="cx"> # that should be the only work unit so don't continue if something else
</span><span class="cx"> # got in there
</span><span class="cx"> self.assertEquals(list(self.holders[0]._q.queue), [])
</span><span class="cx"> self.assertEquals(len(self.holders), 1)
</span><span class="cx"> self.flushHolders()
</span><span class="cx"> stopResult = self.resultOf(self.pool.stopService())
</span><ins>+
</ins><span class="cx"> # Sanity check that we haven't actually stopped it yet
</span><span class="cx"> self.assertEquals(abortResult, [])
</span><ins>+
</ins><span class="cx"> # We haven't fired it yet, so the service had better not have
</span><span class="cx"> # stopped...
</span><span class="cx"> self.assertEquals(stopResult, [])
</span><ins>+
</ins><span class="cx"> d.callback(None)
</span><span class="cx"> self.flushHolders()
</span><span class="cx"> self.assertEquals(abortResult, [None])
</span><span class="lines">@@ -516,16 +529,20 @@
</span><span class="cx"> """
</span><span class="cx"> tc = TrashCollector(self)
</span><span class="cx"> commitExecuted = []
</span><ins>+
</ins><span class="cx"> def carefullyManagedScope():
</span><span class="cx"> t = self.createTransaction()
</span><ins>+
</ins><span class="cx"> def holdAReference():
</span><span class="cx"> """
</span><del>- This is a hook that holds a reference to 't'.
</del><ins>+ This is a hook that holds a reference to "t".
</ins><span class="cx"> """
</span><span class="cx"> commitExecuted.append(True)
</span><span class="cx"> return t.execSQL("teardown", [])
</span><ins>+
</ins><span class="cx"> hook(t, holdAReference)
</span><span class="cx"> finish(t)
</span><ins>+
</ins><span class="cx"> self.failIf(commitExecuted, "Commit hook executed.")
</span><span class="cx"> carefullyManagedScope()
</span><span class="cx"> tc.checkTrash()
</span><span class="lines">@@ -535,32 +552,40 @@
</span><span class="cx"> """
</span><span class="cx"> Committing a transaction does not cause gc garbage.
</span><span class="cx"> """
</span><del>- self.circularReferenceTest(lambda txn: txn.commit(),
- lambda txn, hook: txn.preCommit(hook))
</del><ins>+ self.circularReferenceTest(
+ lambda txn: txn.commit(),
+ lambda txn, hook: txn.preCommit(hook)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_noGarbageOnCommitWithAbortHook(self):
</span><span class="cx"> """
</span><span class="cx"> Committing a transaction does not cause gc garbage.
</span><span class="cx"> """
</span><del>- self.circularReferenceTest(lambda txn: txn.commit(),
- lambda txn, hook: txn.postAbort(hook))
</del><ins>+ self.circularReferenceTest(
+ lambda txn: txn.commit(),
+ lambda txn, hook: txn.postAbort(hook)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_noGarbageOnAbort(self):
</span><span class="cx"> """
</span><span class="cx"> Aborting a transaction does not cause gc garbage.
</span><span class="cx"> """
</span><del>- self.circularReferenceTest(lambda txn: txn.abort(),
- lambda txn, hook: txn.preCommit(hook))
</del><ins>+ self.circularReferenceTest(
+ lambda txn: txn.abort(),
+ lambda txn, hook: txn.preCommit(hook)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_noGarbageOnAbortWithPostCommitHook(self):
</span><span class="cx"> """
</span><span class="cx"> Aborting a transaction does not cause gc garbage.
</span><span class="cx"> """
</span><del>- self.circularReferenceTest(lambda txn: txn.abort(),
- lambda txn, hook: txn.postCommit(hook))
</del><ins>+ self.circularReferenceTest(
+ lambda txn: txn.abort(),
+ lambda txn, hook: txn.postCommit(hook)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_tooManyConnectionsWhileOthersFinish(self):
</span><span class="lines">@@ -573,7 +598,8 @@
</span><span class="cx"> self.pauseHolders()
</span><span class="cx"> a.abort()
</span><span class="cx"> b.abort()
</span><del>- # Remove the holders for the existing connections, so that the 'extra'
</del><ins>+
+ # Remove the holders for the existing connections, so that the "extra"
</ins><span class="cx"> # connection() call wins the race and gets executed first.
</span><span class="cx"> self.holders[:] = []
</span><span class="cx"> self.createTransaction()
</span><span class="lines">@@ -640,7 +666,7 @@
</span><span class="cx"> def test_reConnectWhenFirstExecFails(self):
</span><span class="cx"> """
</span><span class="cx"> Generally speaking, DB-API 2.0 adapters do not provide information
</span><del>- about the cause of a failed 'execute' method; they definitely don't
</del><ins>+ about the cause of a failed C{execute} method; they definitely don't
</ins><span class="cx"> provide it in a way which can be identified as related to the syntax of
</span><span class="cx"> the query, the state of the database itself, the state of the
</span><span class="cx"> connection, etc.
</span><span class="lines">@@ -650,7 +676,7 @@
</span><span class="cx"> exceptions which are raised by the I{first} statement executed in a
</span><span class="cx"> transaction.
</span><span class="cx"> """
</span><del>- # Allow 'connect' to succeed. This should behave basically the same
</del><ins>+ # Allow C{connect} to succeed. This should behave basically the same
</ins><span class="cx"> # whether connect() happened to succeed in some previous transaction
</span><span class="cx"> # and it's recycling the underlying transaction, or connect() just
</span><span class="cx"> # succeeded. Either way you just have a _SingleTxn wrapping a
</span><span class="lines">@@ -658,31 +684,37 @@
</span><span class="cx"> txn = self.createTransaction()
</span><span class="cx"> self.assertEquals(len(self.factory.connections), 1,
</span><span class="cx"> "Sanity check failed.")
</span><ins>+
</ins><span class="cx"> class CustomExecuteFailed(Exception):
</span><span class="cx"> """
</span><del>- Custom 'execute-failed' exception.
</del><ins>+ Custom "execute-failed" exception.
</ins><span class="cx"> """
</span><ins>+
</ins><span class="cx"> self.factory.connections[0].executeWillFail(CustomExecuteFailed)
</span><span class="cx"> results = self.resultOf(txn.execSQL("hello, world!"))
</span><span class="cx"> [[[counter, echo]]] = results
</span><span class="cx"> self.assertEquals("hello, world!", echo)
</span><ins>+
</ins><span class="cx"> # Two execution attempts should have been made, one on each connection.
</span><span class="cx"> # The first failed with a RuntimeError, but that is deliberately
</span><span class="cx"> # obscured, because then we tried again and it succeeded.
</span><del>- self.assertEquals(len(self.factory.connections), 2,
- "No new connection opened.")
</del><ins>+ self.assertEquals(
+ len(self.factory.connections), 2,
+ "No new connection opened."
+ )
</ins><span class="cx"> self.assertEquals(self.factory.connections[0].executions, 1)
</span><span class="cx"> self.assertEquals(self.factory.connections[1].executions, 1)
</span><span class="cx"> self.assertEquals(self.factory.connections[0].closed, True)
</span><span class="cx"> self.assertEquals(self.factory.connections[1].closed, False)
</span><span class="cx">
</span><del>- # Nevertheless, since there is currently no classification of 'safe'
</del><ins>+ # Nevertheless, since there is currently no classification of "safe"
</ins><span class="cx"> # errors, we should probably log these messages when they occur.
</span><span class="cx"> self.assertEquals(len(self.flushLoggedErrors(CustomExecuteFailed)), 1)
</span><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_reConnectWhenFirstExecOnExistingConnectionFails(
</span><del>- self, moreFailureSetup=lambda factory: None):
</del><ins>+ self, moreFailureSetup=lambda factory: None
+ ):
</ins><span class="cx"> """
</span><span class="cx"> Another situation that might arise is that a connection will be
</span><span class="cx"> successfully connected, executed and recycled into the connection pool;
</span><span class="lines">@@ -691,19 +723,23 @@
</span><span class="cx"> """
</span><span class="cx"> txn = self.createTransaction()
</span><span class="cx"> moreFailureSetup(self.factory)
</span><del>- self.assertEquals(len(self.factory.connections), 1,
- "Sanity check failed.")
</del><ins>+ self.assertEquals(
+ len(self.factory.connections), 1, "Sanity check failed."
+ )
</ins><span class="cx"> results = self.resultOf(txn.execSQL("hello, world!"))
</span><span class="cx"> txn.commit()
</span><span class="cx"> [[[counter, echo]]] = results
</span><span class="cx"> self.assertEquals("hello, world!", echo)
</span><span class="cx"> txn2 = self.createTransaction()
</span><del>- self.assertEquals(len(self.factory.connections), 1,
- "Sanity check failed.")
</del><ins>+ self.assertEquals(
+ len(self.factory.connections), 1, "Sanity check failed."
+ )
+
</ins><span class="cx"> class CustomExecFail(Exception):
</span><span class="cx"> """
</span><del>- Custom 'execute()' failure.
</del><ins>+ Custom C{execute()} failure.
</ins><span class="cx"> """
</span><ins>+
</ins><span class="cx"> self.factory.connections[0].executeWillFail(CustomExecFail)
</span><span class="cx"> results = self.resultOf(txn2.execSQL("second try!"))
</span><span class="cx"> txn2.commit()
</span><span class="lines">@@ -721,13 +757,16 @@
</span><span class="cx"> L{test_reConnectWhenFirstExecOnExistingConnectionFails}, the
</span><span class="cx"> failure should be logged, but transparent to application code.
</span><span class="cx"> """
</span><ins>+
</ins><span class="cx"> class BindingSpecificException(Exception):
</span><span class="cx"> """
</span><span class="cx"> Exception that's a placeholder for something that a database
</span><span class="cx"> binding might raise.
</span><span class="cx"> """
</span><ins>+
</ins><span class="cx"> def alsoFailClose(factory):
</span><span class="cx"> factory.childCloseWillFail(BindingSpecificException())
</span><ins>+
</ins><span class="cx"> t = self.test_reConnectWhenFirstExecOnExistingConnectionFails(
</span><span class="cx"> alsoFailClose
</span><span class="cx"> )
</span><span class="lines">@@ -742,8 +781,10 @@
</span><span class="cx"> commit.
</span><span class="cx"> """
</span><span class="cx"> txn = self.createTransaction()
</span><ins>+
</ins><span class="cx"> def simple():
</span><span class="cx"> simple.done = True
</span><ins>+
</ins><span class="cx"> simple.done = False
</span><span class="cx"> txn.preCommit(simple)
</span><span class="cx"> self.assertEquals(simple.done, False)
</span><span class="lines">@@ -760,14 +801,19 @@
</span><span class="cx"> """
</span><span class="cx"> txn = self.createTransaction()
</span><span class="cx"> d = Deferred()
</span><ins>+
</ins><span class="cx"> def wait():
</span><span class="cx"> wait.started = True
</span><ins>+
</ins><span class="cx"> def executed(it):
</span><span class="cx"> wait.sqlResult = it
</span><ins>+
</ins><span class="cx"> # To make sure the _underlying_ commit operation was Deferred, we
</span><span class="cx"> # have to execute some SQL to make sure it happens.
</span><del>- return (d.addCallback(lambda ignored: txn.execSQL("some test sql"))
- .addCallback(executed))
</del><ins>+ d.addCallback(lambda ignored: txn.execSQL("some test sql"))
+ d.addCallback(executed)
+ return d
+
</ins><span class="cx"> wait.started = False
</span><span class="cx"> wait.sqlResult = None
</span><span class="cx"> txn.preCommit(wait)
</span><span class="lines">@@ -796,10 +842,13 @@
</span><span class="cx"> test.aborted = False
</span><span class="cx"> # Create transaction and add monitoring hooks.
</span><span class="cx"> txn = self.createTransaction()
</span><ins>+
</ins><span class="cx"> def didCommit():
</span><span class="cx"> test.committed = True
</span><ins>+
</ins><span class="cx"> def didAbort():
</span><span class="cx"> test.aborted = True
</span><ins>+
</ins><span class="cx"> txn.postCommit(didCommit)
</span><span class="cx"> txn.postAbort(didAbort)
</span><span class="cx"> txn.preCommit(flawedCallable)
</span><span class="lines">@@ -811,8 +860,10 @@
</span><span class="cx">
</span><span class="cx"> def failer():
</span><span class="cx"> return fail(ZeroDivisionError())
</span><ins>+
</ins><span class="cx"> def raiser():
</span><span class="cx"> raise EOFError()
</span><ins>+
</ins><span class="cx"> test(failer, ZeroDivisionError)
</span><span class="cx"> test(raiser, EOFError)
</span><span class="cx">
</span><span class="lines">@@ -834,7 +885,8 @@
</span><span class="cx"> self.factory.rollbackFail = True
</span><span class="cx"> [x] = self.resultOf(txn.commit())
</span><span class="cx">
</span><del>- # No statements have been executed, so 'commit' will *not* be executed.
</del><ins>+ # No statements have been executed, so C{commit} will *not* be
+ # executed.
</ins><span class="cx"> self.assertEquals(self.factory.commitFail, True)
</span><span class="cx"> self.assertIdentical(x, None)
</span><span class="cx"> self.assertEquals(len(self.pool._free), 1)
</span><span class="lines">@@ -865,13 +917,15 @@
</span><span class="cx"> [f] = self.resultOf(txn.execSQL("divide by zero", []))
</span><span class="cx"> f.trap(self.translateError(ZeroDivisionError))
</span><span class="cx"> self.assertEquals(self.factory.connections[0].executions, 2)
</span><ins>+
</ins><span class="cx"> # Reconnection should work exactly as before.
</span><span class="cx"> self.assertEquals(self.factory.connections[0].closed, False)
</span><ins>+
</ins><span class="cx"> # Application code has to roll back its transaction at this point,
</span><span class="cx"> # since it failed (and we don't necessarily know why it failed: not
</span><span class="cx"> # enough information).
</span><span class="cx"> self.resultOf(txn.abort())
</span><del>- self.factory.connections[0].executions = 0 # re-set for next test
</del><ins>+ self.factory.connections[0].executions = 0 # re-set for next test
</ins><span class="cx"> self.assertEquals(len(self.factory.connections), 1)
</span><span class="cx"> self.test_reConnectWhenFirstExecFails()
</span><span class="cx">
</span><span class="lines">@@ -892,6 +946,7 @@
</span><span class="cx"> self.assertEquals("maybe change something!", echo)
</span><span class="cx"> self.factory.rollbackFail = True
</span><span class="cx"> [x] = self.resultOf(txn.abort())
</span><ins>+
</ins><span class="cx"> # Abort does not propagate the error on, the transaction merely gets
</span><span class="cx"> # disposed of.
</span><span class="cx"> self.assertIdentical(x, None)
</span><span class="lines">@@ -917,6 +972,7 @@
</span><span class="cx"> self.assertEquals("maybe change something!", echo)
</span><span class="cx"> [x] = self.resultOf(txn.commit())
</span><span class="cx"> x.trap(self.translateError(CommitFail))
</span><ins>+
</ins><span class="cx"> self.assertEquals(len(self.pool._free), 1)
</span><span class="cx"> self.assertEquals(self.pool._finishing, [])
</span><span class="cx"> self.assertEquals(len(self.factory.connections), 2)
</span><span class="lines">@@ -938,9 +994,11 @@
</span><span class="cx"> c = self.resultOf(cb.execSQL("c"))
</span><span class="cx"> cb.end()
</span><span class="cx"> e = self.resultOf(txn.execSQL("e"))
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [("a", []), ("b", []), ("c", []), ("d", []),
- ("e", [])])
</del><ins>+
+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions,
+ [("a", []), ("b", []), ("c", []), ("d", []), ("e", [])]
+ )
</ins><span class="cx"> self.assertEquals(len(a), 1)
</span><span class="cx"> self.assertEquals(len(b), 1)
</span><span class="cx"> self.assertEquals(len(c), 1)
</span><span class="lines">@@ -964,9 +1022,10 @@
</span><span class="cx"> cb.end()
</span><span class="cx"> self.flushHolders()
</span><span class="cx">
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [("a", []), ("b", []), ("c", []), ("d", []),
- ("e", [])])
</del><ins>+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions,
+ [("a", []), ("b", []), ("c", []), ("d", []), ("e", [])]
+ )
</ins><span class="cx">
</span><span class="cx"> self.assertEquals(len(a), 1)
</span><span class="cx"> self.assertEquals(len(b), 1)
</span><span class="lines">@@ -992,9 +1051,10 @@
</span><span class="cx"> cb1.end()
</span><span class="cx"> flush()
</span><span class="cx"> self.flushHolders()
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [("a", []), ("b", []), ("c", []), ("d", []),
- ("e", [])])
</del><ins>+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions,
+ [("a", []), ("b", []), ("c", []), ("d", []), ("e", [])]
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_twoCommandBlocksLatently(self):
</span><span class="lines">@@ -1028,8 +1088,10 @@
</span><span class="cx"> commitResult = self.resultOf(txn.commit())
</span><span class="cx"> self.resultOf(block.execSQL("in block"))
</span><span class="cx"> self.assertEquals(commitResult, [])
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [("in block", [])])
</del><ins>+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions,
+ [("in block", [])]
+ )
</ins><span class="cx"> block.end()
</span><span class="cx"> self.flushHolders()
</span><span class="cx"> self.assertEquals(commitResult, [None])
</span><span class="lines">@@ -1050,8 +1112,9 @@
</span><span class="cx"> self.assertRaises(AlreadyFinishedError, block2.execSQL, "bar")
</span><span class="cx"> self.assertRaises(AlreadyFinishedError, block.execSQL, "foo")
</span><span class="cx"> self.assertRaises(AlreadyFinishedError, txn.execSQL, "baz")
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [])
</del><ins>+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions, []
+ )
</ins><span class="cx"> # end() should _not_ raise an exception, because this is the sort of
</span><span class="cx"> # thing that might be around a try/finally or try/except; it's just
</span><span class="cx"> # putting the commandBlock itself into a state consistent with the
</span><span class="lines">@@ -1069,8 +1132,9 @@
</span><span class="cx"> block = txn.commandBlock()
</span><span class="cx"> block.end()
</span><span class="cx"> self.assertRaises(AlreadyFinishedError, block.execSQL, "hello")
</span><del>- self.assertEquals(self.factory.connections[0].cursors[0].allExecutions,
- [])
</del><ins>+ self.assertEquals(
+ self.factory.connections[0].cursors[0].allExecutions, []
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def test_commandBlockAfterCommitRaises(self):
</span><span class="lines">@@ -1199,9 +1263,13 @@
</span><span class="cx"> L{ConnectionPoolClient}.
</span><span class="cx"> """
</span><span class="cx"> super(NetworkedPoolHelper, self).setUp()
</span><del>- self.pump = IOPump(ConnectionPoolClient(dialect=self.dialect,
- paramstyle=self.paramstyle),
- ConnectionPoolConnection(self.pool))
</del><ins>+ self.pump = IOPump(
+ ConnectionPoolClient(
+ dialect=self.dialect,
+ paramstyle=self.paramstyle
+ ),
+ ConnectionPoolConnection(self.pool)
+ )
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> def flushHolders(self):
</span><span class="lines">@@ -1300,5 +1368,3 @@
</span><span class="cx"> self.assertEquals(hookOp._hooks, None)
</span><span class="cx"> hookOp.addHook(hook)
</span><span class="cx"> self.assertEquals(hookOp._hooks, None)
</span><del>-
-
</del></span></pre></div>
<a id="twexttrunktwextenterprisetesttest_fixturespy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/test/test_fixtures.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/test/test_fixtures.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/test/test_fixtures.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> from twisted.trial.reporter import TestResult
</span><span class="cx"> from twext.enterprise.adbapi2 import ConnectionPool
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class PoolTests(TestCase):
</span><span class="cx"> """
</span><span class="cx"> Tests for fixtures that create a connection pool.
</span><span class="lines">@@ -37,13 +39,17 @@
</span><span class="cx"> running only for the duration of the test.
</span><span class="cx"> """
</span><span class="cx"> collect = []
</span><ins>+
</ins><span class="cx"> class SampleTest(TestCase):
</span><span class="cx"> def setUp(self):
</span><span class="cx"> self.pool = buildConnectionPool(self)
</span><ins>+
</ins><span class="cx"> def test_sample(self):
</span><span class="cx"> collect.append(self.pool.running)
</span><ins>+
</ins><span class="cx"> def tearDown(self):
</span><span class="cx"> collect.append(self.pool.running)
</span><ins>+
</ins><span class="cx"> r = TestResult()
</span><span class="cx"> t = SampleTest("test_sample")
</span><span class="cx"> t.run(r)
</span></span></pre></div>
<a id="twexttrunktwextenterprisetesttest_lockingpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/test/test_locking.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/test/test_locking.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/test/test_locking.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> create table NAMED_LOCK (LOCK_NAME varchar(255) unique primary key);
</span><span class="cx"> """
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class TestLocking(TestCase):
</span><span class="cx"> """
</span><span class="cx"> Test locking and unlocking a database row.
</span><span class="lines">@@ -87,6 +89,8 @@
</span><span class="cx"> yield NamedLock.acquire(txn1, u"a test lock")
</span><span class="cx">
</span><span class="cx"> txn2 = self.pool.connection()
</span><del>- yield self.assertFailure(NamedLock.acquire(txn2, u"a test lock"), LockTimeout)
</del><ins>+ yield self.assertFailure(
+ NamedLock.acquire(txn2, u"a test lock"), LockTimeout
+ )
</ins><span class="cx"> yield txn2.abort()
</span><span class="cx"> self.flushLoggedErrors()
</span></span></pre></div>
<a id="twexttrunktwextenterprisetesttest_queuepy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/test/test_queue.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/test/test_queue.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/test/test_queue.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> from twisted.trial.unittest import TestCase
</span><span class="cx"> from twisted.python.failure import Failure
</span><span class="cx"> from twisted.internet.defer import (
</span><del>- Deferred, inlineCallbacks, gatherResults, passthru#, returnValue
</del><ins>+ Deferred, inlineCallbacks, gatherResults, passthru
</ins><span class="cx"> )
</span><span class="cx">
</span><span class="cx"> from twisted.application.service import Service, MultiService
</span><span class="lines">@@ -62,6 +62,8 @@
</span><span class="cx"> from twext.enterprise.queue import _BaseQueuer, NonPerformingQueuer
</span><span class="cx"> import twext.enterprise.queue
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class Clock(_Clock):
</span><span class="cx"> """
</span><span class="cx"> More careful L{IReactorTime} fake which mimics the exception behavior of
</span><span class="lines">@@ -122,31 +124,39 @@
</span><span class="cx"> def __init__(self):
</span><span class="cx"> self.commits = []
</span><span class="cx"> self.aborts = []
</span><ins>+
</ins><span class="cx"> def commit(self):
</span><span class="cx"> self.commits.append(Deferred())
</span><span class="cx"> return self.commits[-1]
</span><ins>+
</ins><span class="cx"> def abort(self):
</span><span class="cx"> self.aborts.append(Deferred())
</span><span class="cx"> return self.aborts[-1]
</span><span class="cx">
</span><span class="cx"> createdTxns = []
</span><ins>+
</ins><span class="cx"> def createTxn():
</span><span class="cx"> createdTxns.append(faketxn())
</span><span class="cx"> return createdTxns[-1]
</span><ins>+
</ins><span class="cx"> dfrs = []
</span><ins>+
</ins><span class="cx"> def operation(t):
</span><span class="cx"> self.assertIdentical(t, createdTxns[-1])
</span><span class="cx"> dfrs.append(Deferred())
</span><span class="cx"> return dfrs[-1]
</span><ins>+
</ins><span class="cx"> d = inTransaction(createTxn, operation)
</span><span class="cx"> x = []
</span><span class="cx"> d.addCallback(x.append)
</span><span class="cx"> self.assertEquals(x, [])
</span><span class="cx"> self.assertEquals(len(dfrs), 1)
</span><span class="cx"> dfrs[0].callback(35)
</span><ins>+
</ins><span class="cx"> # Commit in progress, so still no result...
</span><span class="cx"> self.assertEquals(x, [])
</span><span class="cx"> createdTxns[0].commits[0].callback(42)
</span><ins>+
</ins><span class="cx"> # Committed, everything's done.
</span><span class="cx"> self.assertEquals(x, [35])
</span><span class="cx">
</span><span class="lines">@@ -154,31 +164,39 @@
</span><span class="cx">
</span><span class="cx"> class SimpleSchemaHelper(SchemaTestHelper):
</span><span class="cx"> def id(self):
</span><del>- return 'worker'
</del><ins>+ return "worker"
</ins><span class="cx">
</span><ins>+
+
</ins><span class="cx"> SQL = passthru
</span><span class="cx">
</span><del>-schemaText = SQL("""
</del><ins>+schemaText = SQL(
+ """
</ins><span class="cx"> create table DUMMY_WORK_ITEM (WORK_ID integer primary key,
</span><span class="cx"> NOT_BEFORE timestamp,
</span><span class="cx"> A integer, B integer,
</span><span class="cx"> DELETE_ON_LOAD integer default 0);
</span><span class="cx"> create table DUMMY_WORK_DONE (WORK_ID integer primary key,
</span><span class="cx"> A_PLUS_B integer);
</span><del>-""")
</del><ins>+ """
+)
</ins><span class="cx">
</span><del>-nodeSchema = SQL("""
</del><ins>+nodeSchema = SQL(
+ """
</ins><span class="cx"> create table NODE_INFO (HOSTNAME varchar(255) not null,
</span><span class="cx"> PID integer not null,
</span><span class="cx"> PORT integer not null,
</span><span class="cx"> TIME timestamp default current_timestamp not null,
</span><span class="cx"> primary key (HOSTNAME, PORT));
</span><del>-""")
</del><ins>+ """
+)
</ins><span class="cx">
</span><span class="cx"> schema = SchemaSyntax(SimpleSchemaHelper().schemaFromString(schemaText))
</span><span class="cx">
</span><del>-dropSQL = ["drop table {name}".format(name=table.model.name)
- for table in schema]
</del><ins>+dropSQL = [
+ "drop table {name}".format(name=table.model.name)
+ for table in schema
+]
</ins><span class="cx">
</span><span class="cx">
</span><span class="cx"> class DummyWorkDone(Record, fromTable(schema.DUMMY_WORK_DONE)):
</span><span class="lines">@@ -228,13 +246,16 @@
</span><span class="cx"> L{TableSyntaxByName}.
</span><span class="cx"> """
</span><span class="cx"> client = SchemaAMP(schema)
</span><ins>+
</ins><span class="cx"> class SampleCommand(Command):
</span><del>- arguments = [('table', TableSyntaxByName())]
</del><ins>+ arguments = [("table", TableSyntaxByName())]
+
</ins><span class="cx"> class Receiver(SchemaAMP):
</span><span class="cx"> @SampleCommand.responder
</span><span class="cx"> def gotIt(self, table):
</span><span class="cx"> self.it = table
</span><span class="cx"> return {}
</span><ins>+
</ins><span class="cx"> server = Receiver(schema)
</span><span class="cx"> clientT = StringTransport()
</span><span class="cx"> serverT = StringTransport()
</span><span class="lines">@@ -393,20 +414,25 @@
</span><span class="cx"> connection = Connection(local, remote)
</span><span class="cx"> connection.start()
</span><span class="cx"> d = Deferred()
</span><ins>+
</ins><span class="cx"> class DummyPerformer(object):
</span><span class="cx"> def performWork(self, table, workID):
</span><span class="cx"> self.table = table
</span><span class="cx"> self.workID = workID
</span><span class="cx"> return d
</span><ins>+
</ins><span class="cx"> # Doing real database I/O in this test would be tedious so fake the
</span><span class="cx"> # first method in the call stack which actually talks to the DB.
</span><span class="cx"> dummy = DummyPerformer()
</span><ins>+
</ins><span class="cx"> def chooseDummy(onlyLocally=False):
</span><span class="cx"> return dummy
</span><ins>+
</ins><span class="cx"> peer.choosePerformer = chooseDummy
</span><span class="cx"> performed = local.performWork(schema.DUMMY_WORK_ITEM, 7384)
</span><span class="cx"> performResult = []
</span><span class="cx"> performed.addCallback(performResult.append)
</span><ins>+
</ins><span class="cx"> # Sanity check.
</span><span class="cx"> self.assertEquals(performResult, [])
</span><span class="cx"> connection.flush()
</span><span class="lines">@@ -460,9 +486,11 @@
</span><span class="cx"> )
</span><span class="cx"> yield setup
</span><span class="cx"> yield qpool._periodicLostWorkCheck()
</span><ins>+
</ins><span class="cx"> @transactionally(dbpool.connection)
</span><span class="cx"> def check(txn):
</span><span class="cx"> return DummyWorkDone.all(txn)
</span><ins>+
</ins><span class="cx"> every = yield check
</span><span class="cx"> self.assertEquals([x.aPlusB for x in every], [7])
</span><span class="cx">
</span><span class="lines">@@ -482,11 +510,14 @@
</span><span class="cx"> qpool = PeerConnectionPool(clock, dbpool.connection, 0, schema)
</span><span class="cx"> realChoosePerformer = qpool.choosePerformer
</span><span class="cx"> performerChosen = []
</span><ins>+
</ins><span class="cx"> def catchPerformerChoice():
</span><span class="cx"> result = realChoosePerformer()
</span><span class="cx"> performerChosen.append(True)
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> qpool.choosePerformer = catchPerformerChoice
</span><ins>+
</ins><span class="cx"> @transactionally(dbpool.connection)
</span><span class="cx"> def check(txn):
</span><span class="cx"> return qpool.enqueueWork(
</span><span class="lines">@@ -529,17 +560,21 @@
</span><span class="cx"> qpool = PeerConnectionPool(clock, dbpool.connection, 0, schema)
</span><span class="cx"> realChoosePerformer = qpool.choosePerformer
</span><span class="cx"> performerChosen = []
</span><ins>+
</ins><span class="cx"> def catchPerformerChoice():
</span><span class="cx"> result = realChoosePerformer()
</span><span class="cx"> performerChosen.append(True)
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> qpool.choosePerformer = catchPerformerChoice
</span><ins>+
</ins><span class="cx"> @transactionally(dbpool.connection)
</span><span class="cx"> def check(txn):
</span><span class="cx"> return qpool.enqueueWork(
</span><span class="cx"> txn, DummyWorkItem, a=3, b=9,
</span><span class="cx"> notBefore=datetime.datetime(2012, 12, 12, 12, 12, 0)
</span><span class="cx"> ).whenProposed()
</span><ins>+
</ins><span class="cx"> proposal = yield check
</span><span class="cx">
</span><span class="cx"> clock.advance(1000)
</span><span class="lines">@@ -558,13 +593,16 @@
</span><span class="cx"> clock = Clock()
</span><span class="cx"> peerPool = PeerConnectionPool(clock, None, 4322, schema)
</span><span class="cx"> factory = peerPool.workerListenerFactory()
</span><ins>+
</ins><span class="cx"> def peer():
</span><span class="cx"> p = factory.buildProtocol(None)
</span><span class="cx"> t = StringTransport()
</span><span class="cx"> p.makeConnection(t)
</span><span class="cx"> return p, t
</span><ins>+
</ins><span class="cx"> worker1, _ignore_trans1 = peer()
</span><span class="cx"> worker2, _ignore_trans2 = peer()
</span><ins>+
</ins><span class="cx"> # Ask the worker to do something.
</span><span class="cx"> worker1.performWork(schema.DUMMY_WORK_ITEM, 1)
</span><span class="cx"> self.assertEquals(worker1.currentLoad, 1)
</span><span class="lines">@@ -587,11 +625,13 @@
</span><span class="cx"> cph.setUp(self)
</span><span class="cx"> pcp = PeerConnectionPool(reactor, cph.pool.connection, 4321, schema)
</span><span class="cx"> now = then + datetime.timedelta(seconds=pcp.queueProcessTimeout * 2)
</span><ins>+
</ins><span class="cx"> @transactionally(cph.pool.connection)
</span><span class="cx"> def createOldWork(txn):
</span><span class="cx"> one = DummyWorkItem.create(txn, workID=1, a=3, b=4, notBefore=then)
</span><span class="cx"> two = DummyWorkItem.create(txn, workID=2, a=7, b=9, notBefore=now)
</span><span class="cx"> return gatherResults([one, two])
</span><ins>+
</ins><span class="cx"> pcp.startService()
</span><span class="cx"> cph.flushHolders()
</span><span class="cx"> reactor.advance(pcp.queueProcessTimeout * 2)
</span><span class="lines">@@ -696,23 +736,29 @@
</span><span class="cx"> L{PeerConnectionPool} requires access to a database and the reactor.
</span><span class="cx"> """
</span><span class="cx"> self.store = yield buildStore(self, None)
</span><ins>+
</ins><span class="cx"> def doit(txn):
</span><span class="cx"> return txn.execSQL(schemaText)
</span><del>- yield inTransaction(lambda: self.store.newTransaction("bonus schema"),
- doit)
</del><ins>+
+ yield inTransaction(
+ lambda: self.store.newTransaction("bonus schema"), doit
+ )
+
</ins><span class="cx"> def indirectedTransactionFactory(*a):
</span><span class="cx"> """
</span><del>- Allow tests to replace 'self.store.newTransaction' to provide
</del><ins>+ Allow tests to replace "self.store.newTransaction" to provide
</ins><span class="cx"> fixtures with extra methods on a test-by-test basis.
</span><span class="cx"> """
</span><span class="cx"> return self.store.newTransaction(*a)
</span><ins>+
</ins><span class="cx"> def deschema():
</span><span class="cx"> @inlineCallbacks
</span><span class="cx"> def deletestuff(txn):
</span><span class="cx"> for stmt in dropSQL:
</span><span class="cx"> yield txn.execSQL(stmt)
</span><del>- return inTransaction(lambda *a: self.store.newTransaction(*a),
- deletestuff)
</del><ins>+ return inTransaction(
+ lambda *a: self.store.newTransaction(*a), deletestuff
+ )
</ins><span class="cx"> self.addCleanup(deschema)
</span><span class="cx">
</span><span class="cx"> from twisted.internet import reactor
</span><span class="lines">@@ -725,8 +771,10 @@
</span><span class="cx"> def __init__(self, d):
</span><span class="cx"> super(FireMeService, self).__init__()
</span><span class="cx"> self.d = d
</span><ins>+
</ins><span class="cx"> def startService(self):
</span><span class="cx"> self.d.callback(None)
</span><ins>+
</ins><span class="cx"> d1 = Deferred()
</span><span class="cx"> d2 = Deferred()
</span><span class="cx"> FireMeService(d1).setServiceParent(self.node1)
</span><span class="lines">@@ -762,7 +810,7 @@
</span><span class="cx"> """
</span><span class="cx"> # TODO: this exact test should run against LocalQueuer as well.
</span><span class="cx"> def operation(txn):
</span><del>- # TODO: how does 'enqueue' get associated with the transaction?
</del><ins>+ # TODO: how does "enqueue" get associated with the transaction?
</ins><span class="cx"> # This is not the fact with a raw t.w.enterprise transaction.
</span><span class="cx"> # Should probably do something with components.
</span><span class="cx"> return txn.enqueue(DummyWorkItem, a=3, b=4, workID=4321,
</span><span class="lines">@@ -770,10 +818,16 @@
</span><span class="cx"> result = yield inTransaction(self.store.newTransaction, operation)
</span><span class="cx"> # Wait for it to be executed. Hopefully this does not time out :-\.
</span><span class="cx"> yield result.whenExecuted()
</span><ins>+
</ins><span class="cx"> def op2(txn):
</span><del>- return Select([schema.DUMMY_WORK_DONE.WORK_ID,
- schema.DUMMY_WORK_DONE.A_PLUS_B],
- From=schema.DUMMY_WORK_DONE).on(txn)
</del><ins>+ return Select(
+ [
+ schema.DUMMY_WORK_DONE.WORK_ID,
+ schema.DUMMY_WORK_DONE.A_PLUS_B,
+ ],
+ From=schema.DUMMY_WORK_DONE
+ ).on(txn)
+
</ins><span class="cx"> rows = yield inTransaction(self.store.newTransaction, op2)
</span><span class="cx"> self.assertEquals(rows, [[4321, 7]])
</span><span class="cx">
</span><span class="lines">@@ -784,30 +838,45 @@
</span><span class="cx"> When a L{WorkItem} is concurrently deleted by another transaction, it
</span><span class="cx"> should I{not} perform its work.
</span><span class="cx"> """
</span><del>- # Provide access to a method called 'concurrently' everything using
</del><ins>+ # Provide access to a method called "concurrently" everything using
</ins><span class="cx"> original = self.store.newTransaction
</span><ins>+
</ins><span class="cx"> def decorate(*a, **k):
</span><span class="cx"> result = original(*a, **k)
</span><span class="cx"> result.concurrently = self.store.newTransaction
</span><span class="cx"> return result
</span><ins>+
</ins><span class="cx"> self.store.newTransaction = decorate
</span><span class="cx">
</span><span class="cx"> def operation(txn):
</span><del>- return txn.enqueue(DummyWorkItem, a=30, b=40, workID=5678,
- deleteOnLoad=1,
- notBefore=datetime.datetime.utcnow())
</del><ins>+ return txn.enqueue(
+ DummyWorkItem, a=30, b=40, workID=5678,
+ deleteOnLoad=1,
+ notBefore=datetime.datetime.utcnow()
+ )
+
</ins><span class="cx"> proposal = yield inTransaction(self.store.newTransaction, operation)
</span><span class="cx"> yield proposal.whenExecuted()
</span><ins>+
</ins><span class="cx"> # Sanity check on the concurrent deletion.
</span><span class="cx"> def op2(txn):
</span><del>- return Select([schema.DUMMY_WORK_ITEM.WORK_ID],
- From=schema.DUMMY_WORK_ITEM).on(txn)
</del><ins>+ return Select(
+ [schema.DUMMY_WORK_ITEM.WORK_ID],
+ From=schema.DUMMY_WORK_ITEM
+ ).on(txn)
+
</ins><span class="cx"> rows = yield inTransaction(self.store.newTransaction, op2)
</span><span class="cx"> self.assertEquals(rows, [])
</span><ins>+
</ins><span class="cx"> def op3(txn):
</span><del>- return Select([schema.DUMMY_WORK_DONE.WORK_ID,
- schema.DUMMY_WORK_DONE.A_PLUS_B],
- From=schema.DUMMY_WORK_DONE).on(txn)
</del><ins>+ return Select(
+ [
+ schema.DUMMY_WORK_DONE.WORK_ID,
+ schema.DUMMY_WORK_DONE.A_PLUS_B,
+ ],
+ From=schema.DUMMY_WORK_DONE
+ ).on(txn)
+
</ins><span class="cx"> rows = yield inTransaction(self.store.newTransaction, op3)
</span><span class="cx"> self.assertEquals(rows, [])
</span><span class="cx">
</span></span></pre></div>
<a id="twexttrunktwextenterprisetesttest_utilpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/test/test_util.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/test/test_util.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/test/test_util.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -20,6 +20,8 @@
</span><span class="cx">
</span><span class="cx"> from twext.enterprise.util import parseSQLTimestamp
</span><span class="cx">
</span><ins>+
+
</ins><span class="cx"> class TimestampTests(TestCase):
</span><span class="cx"> """
</span><span class="cx"> Tests for date-related functions.
</span></span></pre></div>
<a id="twexttrunktwextenterpriseutilpy"></a>
<div class="modfile"><h4>Modified: twext/trunk/twext/enterprise/util.py (12087 => 12088)</h4>
<pre class="diff"><span>
<span class="info">--- twext/trunk/twext/enterprise/util.py        2013-12-13 21:51:30 UTC (rev 12087)
+++ twext/trunk/twext/enterprise/util.py        2013-12-13 23:59:41 UTC (rev 12088)
</span><span class="lines">@@ -44,12 +44,12 @@
</span><span class="cx"> @param column: a single value from a column.
</span><span class="cx">
</span><span class="cx"> @return: a converted value based on the type of the input; oracle CLOBs and
</span><del>- datetime timestamps will be converted to strings, unicode values will be
- converted to UTF-8 encoded byte sequences (C{str}s), and floating point
- numbers will be converted to integer types if they are integers. Any
- other types will be left alone.
</del><ins>+ datetime timestamps will be converted to strings, unicode values will
+ be converted to UTF-8 encoded byte sequences (C{str}s), and floating
+ point numbers will be converted to integer types if they are integers.
+ Any other types will be left alone.
</ins><span class="cx"> """
</span><del>- if hasattr(column, 'read'):
</del><ins>+ if hasattr(column, "read"):
</ins><span class="cx"> # Try to detect large objects and format convert them to
</span><span class="cx"> # strings on the fly. We need to do this as we read each
</span><span class="cx"> # row, due to the issue described here -
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> # particular, the part where it says "In particular, do not
</span><span class="cx"> # use the fetchall() method".
</span><span class="cx"> column = column.read()
</span><ins>+
</ins><span class="cx"> elif isinstance(column, datetime):
</span><span class="cx"> # cx_Oracle properly maps the type of timestamps to datetime
</span><span class="cx"> # objects. However, our code is mostly written against
</span><span class="lines">@@ -65,21 +66,22 @@
</span><span class="cx"> # just detect the datetimes and stringify them, for now
</span><span class="cx"> # we'll do that.
</span><span class="cx"> return column.strftime(SQL_TIMESTAMP_FORMAT)
</span><ins>+
</ins><span class="cx"> elif isinstance(column, float):
</span><del>- # cx_Oracle maps _all_ nubmers to float types, which is more consistent,
- # but we expect the database to be able to store integers as integers
- # (in fact almost all the values in our schema are integers), so we map
- # those values which exactly match back into integers.
</del><ins>+ # cx_Oracle maps _all_ nubmers to float types, which is more
+ # consistent, but we expect the database to be able to store integers
+ # as integers (in fact almost all the values in our schema are
+ # integers), so we map those values which exactly match back into
+ # integers.
</ins><span class="cx"> if int(column) == column:
</span><span class="cx"> return int(column)
</span><span class="cx"> else:
</span><span class="cx"> return column
</span><ins>+
</ins><span class="cx"> if isinstance(column, unicode):
</span><span class="cx"> # Finally, we process all data as UTF-8 bytestrings in order to reduce
</span><span class="cx"> # memory consumption. Pass any unicode string values back to the
</span><span class="cx"> # application as unicode.
</span><del>- column = column.encode('utf-8')
</del><ins>+ column = column.encode("utf-8")
+
</ins><span class="cx"> return column
</span><del>-
-
-
</del></span></pre>
</div>
</div>
</body>
</html>