Spotlight Searching in Python - Mac OSX
Diez B. Roggisch
deets at nospam.web.de
Mon Sep 8 03:24:48 EDT 2008
cjstevens at gmail.com schrieb:
> Hi all, I'm having some issues getting a spotlight search to work
> similar to the program demonstrated here:
> http://pyobjc.sourceforge.net/examples/pyobjc-framework-Cocoa/AppKit/PredicateEditorSample/
>
>
> Here is my class, complete with the code I am trying to use it with at
> the end.
>
>
> import objc, sys, os, osax, time
> from Foundation import *
> from ScriptingBridge import *
> from appscript import *
>
>
> class SystemBridge(NSObject):
> """Class to use the scripting bridge to interact with the system"""
> _hideapp = objc.ivar(u"hideapp")
> _volume = objc.ivar(u"volume")
> _filename = objc.ivar(u"filename")
> _filetype = objc.ivar(u"filetype")
> _auth = objc.ivar(u"auth")
> _logout = objc.ivar(u"logout")
> query = objc.ivar(u"query")
> StdAdditions = osax.ScriptingAddition()
>
> def init(self):
> super(SystemBridge, self).init()
> # create and initalize our query
> self.query = NSMetadataQuery.alloc().init()
>
> # setup our Spotlight notifications
> nf = NSNotificationCenter.defaultCenter()
> nf.addObserver_selector_name_object_(self,
> 'queryNotification:', None, self.query)
>
>
>
> # XXX: this framework isn't wrapped yet!
>
> self.query.setSortDescriptors_([NSSortDescriptor.alloc().initWithKey_ascending_('kMDItemDisplayName',
> True)])
> self.query.setDelegate_(self)
>
>
>
> return self
>
> def hideApplication_(self, _hideapp):
> app(u'System Events').processes[_hideapp].visible.set(False)
>
> def loadResultsFromQuery_(self, notif):
> results = notif.object().results()
>
> NSLog("search count = %d", len(results))
>
> # iterate through the array of results, and match to the
> existing stores
> for item in results:
> nameStr = item.valueForAttribute_('kMDItemDisplayName')
> print nameStr
>
>
> def queryNotification_(self, note):
> # the NSMetadataQuery will send back a note when updates are
> happening.
> # By looking at the [note name], we can tell what is happening
> if note.name() ==
> NSMetadataQueryDidStartGatheringNotification:
> # the query has just started
> NSLog("search: started gathering")
>
>
> elif note.name() ==
> NSMetadataQueryDidFinishGatheringNotification:
> # at this point, the query will be done. You may recieve
> an update
> # later on.
> NSLog("search: finished gathering");
> self.loadResultsFromQuery_(note)
>
> elif note.name() ==
> NSMetadataQueryGatheringProgressNotification:
> # the query is still gathering results...
> NSLog("search: progressing...")
>
> elif note.name() == NSMetadataQueryDidUpdateNotification:
> # an update will happen when Spotlight notices that a file
> as
> # added, removed, or modified that affected the search
> results.
> NSLog("search: an update happened.")
>
>
> def spotlightFriendlyPredicate_(self, predicate):
> if predicate == NSPredicate.predicateWithValue_(True) or
> predicate == NSPredicate.predicateWithValue_(False):
> return False
>
> elif isinstance(predicate, NSCompoundPredicate):
>
> type = predicate.compoundPredicateType()
> cleanSubpredicates = []
> for dirtySubpredicate in predicate.subpredicates():
> cleanSubpredicate =
> self.spotlightFriendlyPredicate_(
> dirtySubpredicate)
> if cleanSubpredicate:
> cleanSubpredicates.append(cleanSubpredicate)
>
> if len(cleanSubpredicates) == 0:
> return None
>
> else:
> if len(cleanSubpredicates) == 1 and type !=
> NSNotPredicateType:
> return cleanSubpredicates[0]
>
> else:
> return
> NSCompoundPredicate.alloc().initWithType_subpredicates_(type,
> cleanSubpredicates)
>
> else:
> return predicate
>
> def createNewSearchForPredicate_(self, predicate):
>
> # Format search file type
> thePredicate = NSPredicate.predicateWithFormat_(
> "(kMDItemContentType =
> 'com.apple.iwork.keynote.key')")
> tempPredicate = NSPredicate.predicateWithFormat_(
> "(kMDItemDisplayName IN[c] 'preso')")
> predicate = NSCompoundPredicate.andPredicateWithSubpredicates_(
> [thePredicate, tempPredicate])
>
>
> self.query.setPredicate_(predicate)
> self.query.startQuery()
>
>
> def changeVolume_(self, setvolume):
> self.StdAdditions.set_volume(output_volume=setvolume)
>
> def getVolume_(self):
> return StdAdditions.get_volume_settings()[k.output_volume]
>
>
> _x = SystemBridge.alloc().init()
>
> #predicate = u"kMDItemDisplayName IN[c] 'preso'"
> #predicate = _x.spotlightFriendlyPredicate_(predicate)
> if predicate is not None:
> _x.createNewSearchForPredicate_(predicate)
>
>
>
>
> As you can see, I am trying to use a notifier just like the example
> linked above. The class does not work as expected, and just displays
> "search: started gathering", none of the other notifier events happen
> at all!
>
> Have I missed something out translating this to PyObjC? The weird
> thing is, most of that code is straight from the example which works
> fine, so I can't figure out why mine won't work! Any help would be
> hugely appreciated, I need to get this finished soon!
I can only imagine that you need an event-loop to make notifications
work. That's usually needed under OS X.
Diez
More information about the Python-list
mailing list