[Dev] Code review of ItemCollection changes
John Anderson
john at osafoundation.org
Mon Aug 30 17:04:40 PDT 2004
Hi Stuart & Ted:
As I discussed with each of you, I'd like to get you to code review my
ItemCollection changes.
I've attached only the main changes: ItemCollection.py, a snipped of
parcel XML for ItemCollection and diffs for some minor changes to Ted's
Query.
I'm going to be out tommorrow morning, but will try to get in touch with
you in the afternoon to see if we can do a code review.
John
-------------- next part --------------
__date__ = "$Date: 2004/08/24 01:48:52 $"
__copyright__ = "Copyright (c) 2003-2004 Open Source Applications Foundation"
__license__ = "http://osafoundation.org/Chandler_0.1_license_terms.htm"
import application.Globals as Globals
import repository.item.Item as Item
import repository.query.Query as RepositoryQuery
class ItemCollection2(Item.Item):
def subscribe (self, callbackItem=None, callbackMethodName=None):
"""
Subscribed ItemCollections will automatically results up to date. Optionally,
you can specify a method on an item to be called when the results change. There
may be more than one subscriber.
"""
if not self.isPinned():
self.setPinned()
query = self.createRepositoryQuery()
query.subscribe (self, "onItemCollectionChanged")
self.notifyOfChanges ("multiple changes")
if callbackItem is not None:
self._callbacks [callbackItem.itsUUID] = callbackMethodName
def createRepositoryQuery (self):
self._callbacks = {} # transient
self._query = RepositoryQuery.Query (Globals.repository) # transient
self._updateCount = 0 # transient
self.queryStringStale = True
return self._query
def unsubscribe (self, callbackItem=None):
"""
If you don't specify a callbackItemUUID, all subscriptions will be removed.
When an ItemCollections is unsubcribed, resultsStale may be inaccurate and
the results will not be updated automatically. To update results on an unsubscribed
ItemCollection, call updateResults.
"""
if callbackItem is None:
self._callbacks = {}
else:
del self._callbacks [callbackItem.itsUUID]
if len (self._callbacks) == 0:
remainingSubscribers = self._query.unsubscribe (self)
if remainingSubscribers == 0:
del self._query
del self._callbacks
self.setPinned (False)
def onItemCollectionChanged (self, action):
self.resultsStale = True
self.notifyOfChanges (action)
def notifyOfChanges (self, action):
if self.isPinned() and self._updateCount == 0:
for callbackUUID in self._callbacks.keys():
item = Globals.repository.find (callbackUUID)
method = getattr (type(item), self._callbacks [callbackUUID])
method (item, action)
def add (self, item):
"""
Add an item to the inclusions
"""
if item not in self.inclusions:
self.inclusions.append (item)
if item in self.exclusions:
self.exclusions.remove (item)
if item not in self._results:
self._results.append (item)
self.notifyOfChanges ("entered")
self.queryStringStale = True
def remove (self, item):
"""
Remove an item from the exclusions
"""
if item not in self.exclusions:
self.exclusions.append (item)
if item in self.inclusions:
self.inclusions.remove (item)
if item in self._results:
self._results.remove (item)
self.notifyOfChanges ("exited")
self.queryStringStale = True
def addFilterKind (self, item):
"""
Add an kind to the list of kinds to filter
"""
if item not in self.filterKinds:
self.filterKinds.append (item)
self.notifyOfChanges ("multiple changes")
self.queryStringStale = True
def removeFilterKind (self, item):
"""
Remove an kind to the list of kinds to filter
"""
del self.filterKinds [item]
self.notifyOfChanges ("multiple changes")
self.queryStringStale = True
def beginUpdate (self):
"""
When making lots of modifications to inclusions, exclusion, rule or filterKinds
surround the changes with beginUpdate and endUpdate to avoid causing each change
to send a separate notification as in:
itemCollection.beginUpdate()
try:
for item in list:
itemCollection.add (item)
finally:
itemCollection.endUpdate()
Don't call beginUpdate unless the ItemCollection is subscribed.
"""
self._updateCount += 1
def endUpdate (self):
"""
See endUpdate.
"""
self._updateCount -= 1
if self._updateCount == 0:
self.notifyOfChanges (self, "multiple changes")
def getRule (self):
return self._rule
def setRule (self, value):
"""
When setting the rule, make sure we set resultsStale and queryStringStale
"""
self.resultsStale = True
self.queryStringStale = True
self._rule = value
rule = property (getRule, setRule)
def getResults (self):
"""
Override getting results to make sure it isn't stale
"""
if self.resultsStale or self.queryStringStale:
self.updateResults()
return self._results
results = property (getResults)
def updateResults (self):
"""
Refresh the cached query results by executing the repository query if necessary
"""
try:
query = self._query
except AttributeError:
query = self.createRepositoryQuery()
if self.queryStringStale:
query.queryString, query.args = self.calculateQueryStringAndArgs()
self.queryStringStale = False
self.resultsStale = True
query.execute ()
if self.resultsStale:
self.resultsStale = False
self._results = [index for index in query]
def calculateQueryStringAndArgs (self):
args = {}
rule = self._rule
if len (self.inclusions):
if rule:
rule = "union (" + rule + ",for i in $0 where True)"
else:
rule = "for i in $0 where True"
args ["$0"] = (self.itsUUID, "inclusions")
if rule:
if len (self.exclusions):
rule = "difference (" + rule + ",for i in $1 where True)"
args ["$1"] = (self.isUUID, "exclusions")
if len (self.filterKinds) != 0:
for kind in self.filterKinds:
filterKinds += ", " + kind.itsPath
rule = "union (" + rule + filterKinds + ")"
return (rule, args)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: parcel.xml
Type: text/xml
Size: 3458 bytes
Desc: not available
Url : http://lists.osafoundation.org/pipermail/dev/attachments/20040830/fc7bfe67/parcel.xml
-------------- next part --------------
Index: D:/John/osaf/chandler/repository/query/Query.py
===================================================================
RCS file: /usr/local/cvsrep/chandler/repository/query/Query.py,v
retrieving revision 1.8
diff -b -u -2 -r1.8 Query.py
--- D:/John/osaf/chandler/repository/query/Query.py 30 Aug 2004 19:14:18 -0000 1.8
+++ D:/John/osaf/chandler/repository/query/Query.py 31 Aug 2004 00:01:24 -0000
@@ -30,9 +30,10 @@
self.__rep = repo
self.queryString = queryString
- self.args = []
+ self.args = {}
self._kind = None
self._logical_plan = None
self._predicate = None
self.recursive = True
+ self._callbacks = {}
def execute(self):
@@ -63,16 +64,23 @@
log.debug("execute: %s:%f" % (self.queryString,time.time()-start))
- def subscribe(self):
+ def subscribe(self, callbackItem, callbackMethodName):
"""
This query should subscribe to repository changes
"""
+ self._callbacks [callbackItem.itsUUID] = callbackMethodName
log.debug("RepoQuery<>.subscribe(): %s" % (self.queryString))
self.__rep.addNotificationCallback(self.queryCallback)
- def unsubscribe(self):
+ def unsubscribe(self, callbackItem=None):
"""
- This query should stop subscribing to repository changes
+ This query should stop subscribing to repository changes. If you don't specify a
+ callbackItemUUID, all subscriptions will be removed.
"""
+ if callbackItem is None:
+ self._callbacks = {}
+ else:
+ del self._callbacks [callbackItem.itsUUID]
self.__rep.removeNotificationCallback(self.queryCallback)
+ return len (self._callbacks)
def queryCallback(self, view, changes, notification, **kwds):
@@ -115,4 +123,10 @@
if changed:
log.debug("RepoQuery.queryCallback: %s %s query result" % (uuid, action))
+ if len (self._callbacks):
+ for callbackUUID in self._callbacks.keys():
+ item = view.find (callbackUUID)
+ method = getattr (type(item), self._callbacks [callbackUUID])
+ method (item, action)
+ else:
view.findPath('//parcels/osaf/framework/query_changed').Post( {'query' : i.itsUUID, 'action': action} )
log.debug("queryCallback: %s:%f" % (self.queryString, time.time()-start))
@@ -153,5 +167,7 @@
return ('kind', kind)
if name.startswith('$'): # variable argument
- return ('arg',self.args[int(name[1:])-1])
+ itemUUID, attribute = self.args[name]
+ item = self.__rep.find (itemUUID)
+ return ('arg',item.getAttributeValue(attribute))
assert False, "lookup_source couldn't handle %s" % name
More information about the Dev
mailing list