Spotlight Searching in Python - Mac OSX

Diez B. Roggisch deets at nospam.web.de
Mon Sep 8 09:24:48 CEST 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