<!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>[9911] CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py</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/9911">9911</a></dd>
<dt>Author</dt> <dd>gaya@apple.com</dd>
<dt>Date</dt> <dd>2012-10-09 13:13:47 -0700 (Tue, 09 Oct 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>merge in changeset/9910 from trunk</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServerbranchesusersgayasharedgroupstxdavcommondatastoresqlpy">CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServerbranchesusersgayasharedgroupstxdavcommondatastoresqlpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py (9910 => 9911)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py        2012-10-09 20:11:51 UTC (rev 9910)
+++ CalendarServer/branches/users/gaya/sharedgroups/txdav/common/datastore/sql.py        2012-10-09 20:13:47 UTC (rev 9911)
</span><span class="lines">@@ -217,6 +217,7 @@
</span><span class="cx">         self._migrating = state
</span><span class="cx">         self._enableNotifications = not state
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def setUpgrading(self, state):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Set the &quot;upgrading&quot; state
</span><span class="lines">@@ -224,6 +225,7 @@
</span><span class="cx">         self._enableNotifications = not state
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class TransactionStatsCollector(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Used to log each SQL query and statistics about that query during the course of a single transaction.
</span><span class="lines">@@ -235,6 +237,7 @@
</span><span class="cx">         self.logFileName = logFileName
</span><span class="cx">         self.statements = []
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def startStatement(self, sql, args):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Called prior to an SQL query being run.
</span><span class="lines">@@ -243,7 +246,7 @@
</span><span class="cx">         @type sql: C{str}
</span><span class="cx">         @param args: the arguments (binds) to the SQL statement
</span><span class="cx">         @type args: C{list}
</span><del>-        
</del><ins>+
</ins><span class="cx">         @return: C{tuple} containing the index in the statement list for this statement, and the start time
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         args = [&quot;%s&quot; % (arg,) for arg in args]
</span><span class="lines">@@ -251,6 +254,7 @@
</span><span class="cx">         self.statements.append([&quot;%s %s&quot; % (sql, args,), 0, 0])
</span><span class="cx">         return len(self.statements) - 1, time.time()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def endStatement(self, context, rows):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Called after an SQL query has executed.
</span><span class="lines">@@ -264,6 +268,7 @@
</span><span class="cx">         self.statements[index][1] = len(rows) if rows else 0
</span><span class="cx">         self.statements[index][2] = time.time() - tstamp
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def printReport(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Print a report of all the SQL statements executed to date.
</span><span class="lines">@@ -289,6 +294,8 @@
</span><span class="cx">         else:
</span><span class="cx">             log.error(toFile.getvalue())
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> class CommonStoreTransactionMonitor(object):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Object that monitors the state of a transaction over time and logs or times out
</span><span class="lines">@@ -310,6 +317,7 @@
</span><span class="cx">         self._installLogTimer()
</span><span class="cx">         self._installTimeout()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _cleanTxn(self):
</span><span class="cx">         self.txn = None
</span><span class="cx">         if self.delayedLog:
</span><span class="lines">@@ -319,6 +327,7 @@
</span><span class="cx">             self.delayedTimeout.cancel()
</span><span class="cx">             self.delayedTimeout = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _installLogTimer(self):
</span><span class="cx">         def _logTransactionWait():
</span><span class="cx">             if self.txn is not None:
</span><span class="lines">@@ -328,6 +337,7 @@
</span><span class="cx">         if self.logTimerSeconds:
</span><span class="cx">             self.delayedLog = self.callLater(self.logTimerSeconds, _logTransactionWait)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _installTimeout(self):
</span><span class="cx">         def _forceAbort():
</span><span class="cx">             if self.txn is not None:
</span><span class="lines">@@ -444,6 +454,7 @@
</span><span class="cx">             Where=cs.NAME == Parameter('name'),
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def calendarserverValue(self, key):
</span><span class="cx">         result = yield self._calendarserver.on(self, name=key)
</span><span class="lines">@@ -507,6 +518,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return NotificationCollection.notificationsWithUID(self, uid, create)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _insertAPNSubscriptionQuery(cls): #@NoSelf
</span><span class="cx">         apn = schema.APN_SUBSCRIPTIONS
</span><span class="lines">@@ -648,9 +660,11 @@
</span><span class="cx">     def isNotifiedAlready(self, obj):
</span><span class="cx">         return obj in self._notifiedAlready
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def notificationAddedForObject(self, obj):
</span><span class="cx">         self._notifiedAlready.add(obj)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def isBumpedAlready(self, obj):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Indicates whether or not bumpAddedForObject has already been
</span><span class="lines">@@ -659,6 +673,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return obj in self._bumpedAlready
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def bumpAddedForObject(self, obj):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Records the fact that a bumpModified( ) call has already been
</span><span class="lines">@@ -754,13 +769,14 @@
</span><span class="cx">             # caller shouldn't be paying attention anyway.
</span><span class="cx">             block.end()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def execSQL(self, *a, **kw):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute some SQL (delegate to L{IAsyncTransaction}).
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         if self._stats:
</span><del>-            statsContext = self._stats.startStatement(a[0], a[1])
</del><ins>+            statsContext = self._stats.startStatement(a[0], a[1] if len(a) &gt; 1 else ())
</ins><span class="cx">         self.currentStatement = a[0]
</span><span class="cx">         if self._store.logTransactionWaits and a[0].split(&quot; &quot;, 1)[0].lower() in (&quot;insert&quot;, &quot;update&quot;, &quot;delete&quot;,):
</span><span class="cx">             self.iudCount += 1
</span><span class="lines">@@ -777,14 +793,15 @@
</span><span class="cx">                 self._stats.endStatement(statsContext, results)
</span><span class="cx">         returnValue(results)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def execSQLBlock(self, sql):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Execute a block of SQL by parsing it out into individual statements and execute
</span><span class="cx">         each of those.
</span><del>-        
</del><ins>+
</ins><span class="cx">         FIXME: temporary measure for handling large schema upgrades. This should NOT be used
</span><del>-        for regular SQL operations - only upgrades. 
</del><ins>+        for regular SQL operations - only upgrades.
</ins><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         parsed = parse(sql)
</span><span class="cx">         for stmt in parsed:
</span><span class="lines">@@ -795,6 +812,7 @@
</span><span class="cx">             stmt = str(stmt).rstrip(&quot;;&quot;)
</span><span class="cx">             yield self.execSQL(stmt)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def commit(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Commit the transaction and execute any post-commit hooks.
</span><span class="lines">@@ -816,7 +834,7 @@
</span><span class="cx">         co = schema.CALENDAR_OBJECT
</span><span class="cx">         cb = schema.CALENDAR_BIND
</span><span class="cx">         tr = schema.TIME_RANGE
</span><del>-        kwds = { }
</del><ins>+        kwds = {}
</ins><span class="cx">         if limited:
</span><span class="cx">             kwds[&quot;Limit&quot;] = Parameter(&quot;batchSize&quot;)
</span><span class="cx">         return Select(
</span><span class="lines">@@ -864,7 +882,7 @@
</span><span class="cx">             if cutoff &lt; truncateLowerLimit:
</span><span class="cx">                 raise ValueError(&quot;Cannot query events older than %s&quot; % (truncateLowerLimit.getText(),))
</span><span class="cx"> 
</span><del>-        kwds = { &quot;CutOff&quot; : pyCalendarTodatetime(cutoff) }
</del><ins>+        kwds = {&quot;CutOff&quot;: pyCalendarTodatetime(cutoff)}
</ins><span class="cx">         if batchSize is not None:
</span><span class="cx">             kwds[&quot;batchSize&quot;] = batchSize
</span><span class="cx">             query = self._oldEventsLimited
</span><span class="lines">@@ -948,15 +966,22 @@
</span><span class="cx">         returnValue(count)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class _EmptyCacher(object):
</span><ins>+
</ins><span class="cx">     def set(self, key, value):
</span><span class="cx">         return succeed(True)
</span><ins>+
+
</ins><span class="cx">     def get(self, key, withIdentifier=False):
</span><span class="cx">         return succeed(None)
</span><ins>+
+
</ins><span class="cx">     def delete(self, key):
</span><span class="cx">         return succeed(True)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class CommonHome(LoggingMixIn):
</span><span class="cx"> 
</span><span class="cx">     # All these need to be initialized by derived classes for each store type
</span><span class="lines">@@ -1017,6 +1042,7 @@
</span><span class="cx">         return Select([home.RESOURCE_ID],
</span><span class="cx">                       From=home, Where=home.OWNER_UID == Parameter(&quot;ownerUID&quot;))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _ownerFromResourceID(cls): #@NoSelf
</span><span class="cx">         home = cls._homeSchema
</span><span class="lines">@@ -1024,6 +1050,7 @@
</span><span class="cx">                       From=home,
</span><span class="cx">                       Where=home.RESOURCE_ID == Parameter(&quot;resourceID&quot;))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _metaDataQuery(cls): #@NoSelf
</span><span class="cx">         metadata = cls._homeMetaDataSchema
</span><span class="lines">@@ -1031,6 +1058,7 @@
</span><span class="cx">                       From=metadata,
</span><span class="cx">                       Where=metadata.RESOURCE_ID == Parameter(&quot;resourceID&quot;))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def initFromStore(self, no_cache=False):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1183,6 +1211,7 @@
</span><span class="cx">         self._childrenLoaded = True
</span><span class="cx">         returnValue(results)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def listChildren(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Retrieve the names of the children in this home.
</span><span class="lines">@@ -1216,6 +1245,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._childClass.objectWithName(self, name)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @memoizedKey(&quot;resourceID&quot;, &quot;_children&quot;)
</span><span class="cx">     def childWithID(self, resourceID):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1227,6 +1257,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._childClass.objectWithID(self, resourceID)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def invitedChildWithName(self, name):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Retrieve the invited child with the given C{name} contained in this
</span><span class="lines">@@ -1237,6 +1268,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._childClass.invitedObjectWithName(self, name)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def createChildWithName(self, name):
</span><span class="cx">         if name.startswith(&quot;.&quot;):
</span><span class="lines">@@ -1246,6 +1278,7 @@
</span><span class="cx">         child = (yield self.childWithName(name))
</span><span class="cx">         returnValue(child)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def removeChildWithName(self, name):
</span><span class="cx">         child = yield self.childWithName(name)
</span><span class="lines">@@ -1575,6 +1608,7 @@
</span><span class="cx">         else:
</span><span class="cx">             returnValue(None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _lockLastModifiedQuery(cls): #@NoSelf
</span><span class="cx">         meta = cls._homeMetaDataSchema
</span><span class="lines">@@ -1585,6 +1619,7 @@
</span><span class="cx">             NoWait=True
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _changeLastModifiedQuery(cls): #@NoSelf
</span><span class="cx">         meta = cls._homeMetaDataSchema
</span><span class="lines">@@ -1592,6 +1627,7 @@
</span><span class="cx">                       Where=meta.RESOURCE_ID == Parameter(&quot;resourceID&quot;),
</span><span class="cx">                       Return=meta.MODIFIED)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def bumpModified(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1625,6 +1661,7 @@
</span><span class="cx">         except AllRetriesFailed:
</span><span class="cx">             log.debug(&quot;CommonHome.bumpModified failed&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def notifyChanged(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1677,6 +1714,7 @@
</span><span class="cx">         _ignore_uuid, revision = token.split(&quot;_&quot;, 1)
</span><span class="cx">         return int(revision)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def syncToken(self):
</span><span class="cx">         if self._syncTokenRevision is None:
</span><span class="lines">@@ -1715,7 +1753,7 @@
</span><span class="cx">             (yield self._objectNamesSinceRevisionQuery.on(
</span><span class="cx">                 self._txn, revision=token, resourceID=self._resourceID))
</span><span class="cx">         ]
</span><del>-        results.sort(key=lambda x:x[1])
</del><ins>+        results.sort(key=lambda x: x[1])
</ins><span class="cx"> 
</span><span class="cx">         changed = []
</span><span class="cx">         deleted = []
</span><span class="lines">@@ -2034,6 +2072,7 @@
</span><span class="cx">             cls._homeChildMetaDataSchema.MODIFIED,
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     def metadataAttributes(cls):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2049,6 +2088,7 @@
</span><span class="cx">             &quot;_modified&quot;,
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def listObjects(cls, home):
</span><span class="lines">@@ -2070,6 +2110,7 @@
</span><span class="cx">         return cls._bindFor((bind.HOME_RESOURCE_ID == Parameter(&quot;homeID&quot;))
</span><span class="cx">                             .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED))
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def listInvitedObjects(cls, home):
</span><span class="lines">@@ -2112,11 +2153,11 @@
</span><span class="cx">     def _updateBindColumnsQuery(cls, columnMap): #@NoSelf
</span><span class="cx">         bind = cls._bindSchema
</span><span class="cx">         return Update(columnMap,
</span><del>-                      Where=
-                      (bind.RESOURCE_ID == Parameter(&quot;resourceID&quot;))
</del><ins>+                      Where=(bind.RESOURCE_ID == Parameter(&quot;resourceID&quot;))
</ins><span class="cx">                       .And(bind.HOME_RESOURCE_ID == Parameter(&quot;homeID&quot;)),
</span><span class="cx">                       Return=bind.RESOURCE_NAME)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _updateBindQuery(cls): #@NoSelf
</span><span class="cx">         bind = cls._bindSchema
</span><span class="lines">@@ -2235,7 +2276,7 @@
</span><span class="cx">                 if shareeView._bindStatus == _BIND_STATUS_ACCEPTED:
</span><span class="cx">                     yield shareeView._initSyncToken()
</span><span class="cx">                 elif shareeView._bindStatus == _BIND_STATUS_DECLINED:
</span><del>-                    shareeView._deletedSyncToken(sharedRemoval=True);
</del><ins>+                    shareeView._deletedSyncToken(sharedRemoval=True)
</ins><span class="cx"> 
</span><span class="cx">             if message:
</span><span class="cx">                 shareeView._bindMessage = columnMap[bind.MESSAGE]
</span><span class="lines">@@ -2253,7 +2294,6 @@
</span><span class="cx">         returnValue(shareeView._name)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def unshareWith(self, shareeHome):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2268,19 +2308,18 @@
</span><span class="cx">         @return: a L{Deferred} which will fire with the previously-used name.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-
</del><span class="cx">         #remove sync tokens
</span><span class="cx">         shareeChildren = yield shareeHome.children()
</span><span class="cx">         for shareeChild in shareeChildren:
</span><span class="cx">             if not shareeChild.owned() and shareeChild._resourceID == self._resourceID:
</span><del>-                shareeChild._deletedSyncToken(sharedRemoval=True);
</del><ins>+                shareeChild._deletedSyncToken(sharedRemoval=True)
</ins><span class="cx"> 
</span><span class="cx">                 queryCacher = self._txn._queryCacher
</span><span class="cx">                 if queryCacher:
</span><span class="cx">                     cacheKey = queryCacher.keyForObjectWithName(shareeHome._resourceID, shareeChild._name)
</span><span class="cx">                     queryCacher.invalidateAfterCommit(self._txn, cacheKey)
</span><span class="cx"> 
</span><del>-                break;
</del><ins>+                break
</ins><span class="cx"> 
</span><span class="cx">         bind = self._bindSchema
</span><span class="cx">         rows = yield Delete(
</span><span class="lines">@@ -2308,30 +2347,35 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._bindMode
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def owned(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @see: L{ICalendar.owned}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._bindMode == _BIND_MODE_OWN
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def shareStatus(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @see: L{ICalendar.shareStatus}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._bindStatus
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def shareMessage(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @see: L{ICalendar.shareMessage}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self._bindMessage
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def shareUID(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         @see: L{ICalendar.shareUID}
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return self.name()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def unshare(self, homeType):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2366,6 +2410,7 @@
</span><span class="cx">                   Where=condition
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _sharedBindForResourceID(cls): #@NoSelf
</span><span class="cx">         bind = cls._bindSchema
</span><span class="lines">@@ -2375,7 +2420,6 @@
</span><span class="cx">                             )
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def asShared(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2420,6 +2464,7 @@
</span><span class="cx">                             .And(bind.BIND_STATUS != _BIND_STATUS_ACCEPTED)
</span><span class="cx">                             )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def asInvited(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -2573,6 +2618,7 @@
</span><span class="cx">                                .And(bind.BIND_STATUS == _BIND_STATUS_ACCEPTED)
</span><span class="cx">                                )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def objectWithName(cls, home, name):
</span><span class="lines">@@ -2602,7 +2648,7 @@
</span><span class="cx"> 
</span><span class="cx">             if rows:
</span><span class="cx">                 bindMode, homeID, resourceID, resourceName, bindStatus, bindMessage = rows[0] #@UnusedVariable
</span><del>-                # get ownerHomeID                
</del><ins>+                # get ownerHomeID
</ins><span class="cx">                 if bindMode == _BIND_MODE_OWN:
</span><span class="cx">                     ownerHomeID = homeID
</span><span class="cx">                 else:
</span><span class="lines">@@ -3164,6 +3210,7 @@
</span><span class="cx">             raise NoSuchObjectResourceError
</span><span class="cx">         yield self._removeObjectResource(child)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _removeObjectResource(self, child):
</span><span class="cx">         name = child.name()
</span><span class="lines">@@ -3176,6 +3223,7 @@
</span><span class="cx">             yield self._deleteRevision(name)
</span><span class="cx">             yield self.notifyChanged()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _moveParentUpdateQuery(cls): #@NoSelf
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -3187,6 +3235,7 @@
</span><span class="cx">             Where=obj.RESOURCE_ID == Parameter(&quot;resourceID&quot;)
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def _movedObjectResource(self, child, newparent):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Method that subclasses can override to do an extra DB adjustments when a resource
</span><span class="lines">@@ -3194,12 +3243,13 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         return succeed(True)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def moveObjectResource(self, child, newparent):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Move a child of this collection into another collection without actually removing/re-inserting the data.
</span><span class="cx">         Make sure sync and cache details for both collections are updated.
</span><del>-        
</del><ins>+
</ins><span class="cx">         TODO: check that the resource name does not exist in the new parent, or that the UID
</span><span class="cx">         does not exist there too.
</span><span class="cx"> 
</span><span class="lines">@@ -3232,6 +3282,7 @@
</span><span class="cx">         yield newparent._insertRevision(name)
</span><span class="cx">         yield newparent.notifyChanged()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def objectResourcesHaveProperties(self):
</span><span class="cx">         return False
</span><span class="cx"> 
</span><span class="lines">@@ -3261,6 +3312,7 @@
</span><span class="cx"> 
</span><span class="cx">         @param props: the L{PropertyStore} from C{properties()}.
</span><span class="cx">         &quot;&quot;&quot;
</span><ins>+        pass
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">     # IDataStoreObject
</span><span class="lines">@@ -3289,12 +3341,14 @@
</span><span class="cx">             self._notifiers = ()
</span><span class="cx">         self._notifiers += (notifier,)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def notifierID(self, label=&quot;default&quot;):
</span><span class="cx">         if self._notifiers:
</span><span class="cx">             return self._notifiers[0].getID(label)
</span><span class="cx">         else:
</span><span class="cx">             return None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def nodeName(self, label=&quot;default&quot;):
</span><span class="cx">         if self._notifiers:
</span><span class="lines">@@ -3305,6 +3359,7 @@
</span><span class="cx">         else:
</span><span class="cx">             returnValue(None)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _lockLastModifiedQuery(cls): #@NoSelf
</span><span class="cx">         schema = cls._homeChildMetaDataSchema
</span><span class="lines">@@ -3315,6 +3370,7 @@
</span><span class="cx">             NoWait=True
</span><span class="cx">         )
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _changeLastModifiedQuery(cls): #@NoSelf
</span><span class="cx">         schema = cls._homeChildMetaDataSchema
</span><span class="lines">@@ -3353,6 +3409,7 @@
</span><span class="cx">         except AllRetriesFailed:
</span><span class="cx">             log.debug(&quot;CommonHomeChild.bumpModified failed&quot;)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @inlineCallbacks
</span><span class="cx">     def notifyChanged(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -3370,6 +3427,7 @@
</span><span class="cx">             self._txn.notificationAddedForObject(self)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class CommonObjectResource(LoggingMixIn, FancyEqMixin):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Base class for object resources.
</span><span class="lines">@@ -3447,6 +3505,7 @@
</span><span class="cx"> 
</span><span class="cx">         returnValue(results)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     def _allColumnsWithParentAndNames(cls, names): #@NoSelf
</span><span class="cx">         obj = cls._objectSchema
</span><span class="lines">@@ -3470,6 +3529,7 @@
</span><span class="cx"> 
</span><span class="cx">         returnValue(results)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def _loadAllObjectsWithNames(cls, parent, names):
</span><span class="lines">@@ -3519,11 +3579,13 @@
</span><span class="cx">         objectResource = cls(parent, name, uid, None)
</span><span class="cx">         return objectResource.initFromStore()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     def objectWithID(cls, parent, resourceID):
</span><span class="cx">         objectResource = cls(parent, None, None, resourceID)
</span><span class="cx">         return objectResource.initFromStore()
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classmethod
</span><span class="cx">     @inlineCallbacks
</span><span class="cx">     def create(cls, parent, name, component, metadata):
</span><span class="lines">@@ -3700,7 +3762,7 @@
</span><span class="cx">         @type wait: C{bool}
</span><span class="cx">         @param txn: alternative transaction to use
</span><span class="cx">         @type txn: L{CommonStoreTransaction}
</span><del>-        
</del><ins>+
</ins><span class="cx">         @raise: L{NoSuchObjectResourceError} if resource does not exist, other L{Exception}
</span><span class="cx">                 if already locked and NOWAIT is used.
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -3722,6 +3784,7 @@
</span><span class="cx">     def componentType(self):
</span><span class="cx">         returnValue((yield self.component()).mainType())
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     @classproperty
</span><span class="cx">     def _deleteQuery(cls): #@NoSelf
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -3746,6 +3809,7 @@
</span><span class="cx">         self._modified = None
</span><span class="cx">         self._objectText = None
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def uid(self):
</span><span class="cx">         return self._uid
</span><span class="cx"> 
</span><span class="lines">@@ -3754,7 +3818,6 @@
</span><span class="cx">         return self._name
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     # IDataStoreObject
</span><span class="cx">     def contentType(self):
</span><span class="cx">         raise NotImplementedError()
</span><span class="lines">@@ -3842,12 +3905,10 @@
</span><span class="cx">             notifiers = None
</span><span class="cx">         self._notifiers = notifiers
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _resourceIDFromUIDQuery = Select(
</span><span class="cx">         [_homeSchema.RESOURCE_ID], From=_homeSchema,
</span><span class="cx">         Where=_homeSchema.OWNER_UID == Parameter(&quot;uid&quot;))
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _provisionNewNotificationsQuery = Insert(
</span><span class="cx">         {_homeSchema.OWNER_UID: Parameter(&quot;uid&quot;)},
</span><span class="cx">         Return=_homeSchema.RESOURCE_ID
</span><span class="lines">@@ -3951,7 +4012,6 @@
</span><span class="cx">         self._notificationNames = sorted([result.name() for result in results])
</span><span class="cx">         returnValue(results)
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _notificationUIDsForHomeQuery = Select(
</span><span class="cx">         [schema.NOTIFICATION.NOTIFICATION_UID], From=schema.NOTIFICATION,
</span><span class="cx">         Where=schema.NOTIFICATION.NOTIFICATION_HOME_RESOURCE_ID ==
</span><span class="lines">@@ -4009,7 +4069,6 @@
</span><span class="cx">     def removeNotificationObjectWithName(self, name):
</span><span class="cx">         return self.removeNotificationObjectWithUID(self._nameToUID(name))
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _removeByUIDQuery = Delete(
</span><span class="cx">         From=schema.NOTIFICATION,
</span><span class="cx">         Where=(schema.NOTIFICATION.NOTIFICATION_UID == Parameter(&quot;uid&quot;)).And(
</span><span class="lines">@@ -4024,7 +4083,6 @@
</span><span class="cx">         self._notifications.pop(uid, None)
</span><span class="cx">         yield self._deleteRevision(&quot;%s.xml&quot; % (uid,))
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _initSyncTokenQuery = Insert(
</span><span class="cx">         {
</span><span class="cx">             _revisionsSchema.HOME_RESOURCE_ID : Parameter(&quot;resourceID&quot;),
</span><span class="lines">@@ -4040,7 +4098,6 @@
</span><span class="cx">         self._syncTokenRevision = (yield self._initSyncTokenQuery.on(
</span><span class="cx">             self._txn, resourceID=self._resourceID))[0][0]
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _syncTokenQuery = Select(
</span><span class="cx">         [Max(_revisionsSchema.REVISION)], From=_revisionsSchema,
</span><span class="cx">         Where=_revisionsSchema.HOME_RESOURCE_ID == Parameter(&quot;resourceID&quot;)
</span><span class="lines">@@ -4066,6 +4123,7 @@
</span><span class="cx">             self._notifiers = ()
</span><span class="cx">         self._notifiers += (notifier,)
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def notifierID(self, label=&quot;default&quot;):
</span><span class="cx">         if self._notifiers:
</span><span class="cx">             return self._notifiers[0].getID(label)
</span><span class="lines">@@ -4121,7 +4179,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         # Delete NOTIFICATION rows
</span><span class="cx">         no = schema.NOTIFICATION
</span><del>-        kwds = { &quot;ResourceID&quot; : self._resourceID }
</del><ins>+        kwds = {&quot;ResourceID&quot;: self._resourceID}
</ins><span class="cx">         yield Delete(
</span><span class="cx">             From=no,
</span><span class="cx">             Where=(
</span><span class="lines">@@ -4139,6 +4197,7 @@
</span><span class="cx">         ).on(self._txn, **kwds)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> class NotificationObject(LoggingMixIn, FancyEqMixin):
</span><span class="cx"> 
</span><span class="cx">     implements(INotificationObject)
</span><span class="lines">@@ -4348,7 +4407,6 @@
</span><span class="cx">             self._modified = rows[0][0]
</span><span class="cx">         self._objectText = xmldata
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     _xmlDataFromID = Select(
</span><span class="cx">         [_objectSchema.XML_DATA], From=_objectSchema,
</span><span class="cx">         Where=_objectSchema.RESOURCE_ID == Parameter(&quot;resourceID&quot;))
</span><span class="lines">@@ -4377,6 +4435,7 @@
</span><span class="cx">     def size(self):
</span><span class="cx">         return self._size
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def xmlType(self):
</span><span class="cx">         # NB This is the NotificationType property element
</span><span class="cx">         if isinstance(self._xmlType, str):
</span><span class="lines">@@ -4385,6 +4444,7 @@
</span><span class="cx"> 
</span><span class="cx">         return self._xmlType
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">     def created(self):
</span><span class="cx">         return datetimeMktime(parseSQLTimestamp(self._created))
</span><span class="cx"> 
</span><span class="lines">@@ -4744,6 +4804,3 @@
</span><span class="cx">         # obscure bug.
</span><span class="cx">     else:
</span><span class="cx">         yield t.commit()
</span><del>-
-
-
</del></span></pre>
</div>
</div>

</body>
</html>