def is_valid(self): if isabs(self._program): returnval = exists(self._program) else: returnval = is_program_in_path(self._program) if not returnval: LOGGER.debug("%s does not exist", self._program) return returnval
def is_valid(self): if isabs(self._program): returnval = exists(self._program) else: returnval = is_program_in_path(self._program) if not returnval: LOGGER.debug("%s does not exist", self._program) return returnval
def query_path_programs(self, query, desktop_progs): """ @param query: Query string @param desktop_progs: Names of binaries from .desktop files """ args = query.split(" ") program = args[0] priority = self.get_priority() if len(args) == 1: results = [] for pathdir in PATH: try: pathstat = stat(pathdir) pathmtime = pathstat.st_mtime except OSError: continue indexpair = self._path_indexers.get(pathdir, None) if indexpair is not None: indexer, updatetime = indexpair else: indexer, updatetime = deskbar.core.Indexer.Indexer(), -1 if pathmtime > updatetime: self._scan_path(pathdir, indexer) self._path_indexers[pathdir] = (indexer, time.time()) for match in indexer.look_up(program): if match.get_hash() in desktop_progs: continue match.set_priority(priority + get_priority_for_name(query, program)) results.append(match) return results else: # We have arguments, execute the command as typed in by the user if not (program in desktop_progs) and is_program_in_path(program): match = PathProgramMatch(program, query) match.set_priority(self.get_priority() + EXACT_MATCH_PRIO) return [match] else: return []
def query_path_programs(self, query, desktop_progs): """ @param query: Query string @param desktop_progs: Names of binaries from .desktop files """ args = query.split(" ") program = args[0] priority = self.get_priority() if len(args) == 1: results = [] for pathdir in PATH: try: pathstat = stat(pathdir) pathmtime = pathstat.st_mtime except OSError: continue indexpair = self._path_indexers.get(pathdir, None) if indexpair is not None: indexer, updatetime = indexpair else: indexer, updatetime = deskbar.core.Indexer.Indexer(), -1 if pathmtime > updatetime: self._scan_path(pathdir, indexer) self._path_indexers[pathdir] = (indexer, time.time()) for match in indexer.look_up(program): if match.get_hash() in desktop_progs: continue match.set_priority(priority + get_priority_for_name(query, program)) results.append(match) return results else: # We have arguments, execute the command as typed in by the user if not (program in desktop_progs) and is_program_in_path(program): match = PathProgramMatch(program, query) match.set_priority (self.get_priority() + EXACT_MATCH_PRIO) return [match] else: return []
class BeagleLiveHandler(deskbar.interfaces.Module): INFOS = { 'icon': load_icon("system-search"), "name": _("Beagle Live"), "description": _("Search all of your documents (using Beagle), as you type"), 'version': VERSION, } def __init__(self): deskbar.interfaces.Module.__init__(self) self.__counter_lock = threading.Lock() self.__beagle_lock = threading.Lock() self.__snippet_lock = threading.Lock() self.__finished_lock = threading.Lock() self.__snippet_request = {} # Maps beagle.Hit to beagle.SnippetRequest # We have to store instances for each query term self._counter = {} # Count hits for each hit type self._at_max = { } # Whether we have reached the maximum for a particular hit type before self._beagle_query = {} self.__hits_added_id = {} self.__hits_finished_id = {} self.__finished = { } # Whether we got all matches from beagle for query def initialize(self): self.beagle = beagle.Client() def stop(self): self.beagle = None def query(self, qstring): self.__counter_lock.acquire() self._counter[qstring] = {} self._at_max[qstring] = {} self.__counter_lock.release() self.__finished_lock.acquire() self.__finished[qstring] = False self.__finished_lock.release() try: self.__beagle_lock.acquire() beagle_query = beagle.Query() self.__hits_added_id[qstring] = beagle_query.connect( "hits-added", self._on_hits_added, qstring) self.__hits_finished_id[qstring] = beagle_query.connect( "finished", self._on_finished, qstring) beagle_query.add_text(qstring) self._beagle_query[qstring] = beagle_query LOGGER.debug("Sending beagle query (%r) for '%s'", self._beagle_query[qstring], qstring) try: self.beagle.send_request_async(self._beagle_query[qstring]) except GError, e: LOGGER.exception(e) self._cleanup_query(qstring) finally: self.__beagle_lock.release() def _on_hits_added(self, query, response, qstring): for hit in response.get_hits(): if hit.get_type() not in TYPES: LOGGER.info("Beagle live seen an unknown type: %s", str(hit.get_type())) continue beagle_type = self._get_beagle_type(hit) if beagle_type == None: continue if beagle_type.get_has_snippet(): self._get_snippet(query, hit, qstring, beagle_type) else: self._create_match(hit, beagle_type, qstring) def _on_finished(self, query, response, qstring): LOGGER.debug("Beagle query (%r) for '%s' finished with response %r", query, qstring, response) self.__finished_lock.acquire() self.__finished[qstring] = True self.__finished_lock.release() def _on_snippet_received(self, request, response, hit, qstring, beagle_type): snippet = response.get_snippet() if snippet == None: snippet_text = None else: # Remove trailing whitespaces and escape '%' snippet_text = snippet.strip().replace("%", "%%") self._create_match(hit, beagle_type, qstring, snippet_text) def _on_snippet_closed(self, request, hit, qstring): self._cleanup_snippet(hit) self.__snippet_lock.acquire() n_snippets = len(self.__snippet_request) self.__snippet_lock.release() self.__finished_lock.acquire() finished = self.__finished[qstring] self.__finished_lock.release() # FIXME: This only works when at least one # result has a snippet, otherwise we # miss cleaning up if finished and n_snippets == 0: self._cleanup_query(qstring) self._cleanup_counter(qstring) def _cleanup_counter(self, qstring): self.__counter_lock.acquire() if qstring in self._counter: del self._counter[qstring] del self._at_max[qstring] self.__counter_lock.release() def _cleanup_snippet(self, hit): LOGGER.debug("Cleaning up hit %r", hit) self.__snippet_lock.acquire() del self.__snippet_request[hit] self.__snippet_lock.release() hit.unref() def _cleanup_query(self, qstring): LOGGER.debug("Cleaning up query for '%s'", qstring) # Remove counter for query self.__beagle_lock.acquire() # Disconnect signals, otherwise we receive late matches # when beagle found the query term in a newly indexed file beagle_query = self._beagle_query[qstring] beagle_query.disconnect(self.__hits_added_id[qstring]) beagle_query.disconnect(self.__hits_finished_id[qstring]) del self._beagle_query[qstring] del self.__hits_added_id[qstring] del self.__hits_finished_id[qstring] self.__beagle_lock.release() self.__finished_lock.acquire() del self.__finished[qstring] self.__finished_lock.release() def _get_snippet(self, query, hit, qstring, beagle_type): LOGGER.debug("Retrieving snippet for hit %r", hit) snippet_request = beagle.SnippetRequest() snippet_request.set_query(query) snippet_request.set_hit(hit) hit.ref() snippet_request.connect('response', self._on_snippet_received, hit, qstring, beagle_type) snippet_request.connect('closed', self._on_snippet_closed, hit, qstring) self.__snippet_lock.acquire() self.__snippet_request[hit] = snippet_request self.__snippet_lock.release() try: self.__beagle_lock.acquire() try: self.beagle.send_request_async(snippet_request) except GError, e: LOGGER.exception(e) self._cleanup_snippet(hit) finally: self.__beagle_lock.release() def _get_beagle_type(self, hit): """ Returns the appropriate L{BeagleType} for the given hit @type hit: beagle.Hit @return: L{BeagleType} instance """ hit_type = hit.get_type() snippet = None if hit_type in TYPES: beagle_type = TYPES[hit_type] else: LOGGER.warning("Unknown beagle match type found: %s", result["type"]) return None # Directories are Files in beagle context if hit_type == "File": filetype = hit.get_properties("beagle:FileType") if filetype != None \ and filetype[0] in BEAGLE_FILE_TYPE_TO_TYPES_MAP: beagle_type = TYPES[BEAGLE_FILE_TYPE_TO_TYPES_MAP[filetype[0]]] return beagle_type def _create_match(self, hit, beagle_type, qstring, snippet=None): # Get category cat_type = beagle_type.get_category() result = { "uri": hit.get_uri(), "type": beagle_type, "snippet": snippet, } self.__counter_lock.acquire() # Create new counter for query and type if not cat_type in self._counter[qstring]: self._counter[qstring][cat_type] = 0 # Increase counter self._counter[qstring][cat_type] += 1 if self._counter[qstring][cat_type] > MAX_RESULTS: if cat_type in self._at_max[qstring]: # We already reached the maximum before self.__counter_lock.release() return else: # We reach the maximum for the first time self._at_max[qstring][cat_type] = True self._emit_query_ready(qstring, [ BeagleSearchMatch(qstring, cat_type, beagle_type.get_hit_type()) ]) self.__counter_lock.release() return self.__counter_lock.release() self._get_properties(hit, result) self._escape_pango_markup(result, qstring) self._emit_query_ready(qstring, [ BeagleLiveMatch( result, category=cat_type, priority=self.get_priority()) ]) def _get_properties(self, hit, result): beagle_type = result["type"] name = None for prop in beagle_type.get_name_properties(): try: name = hit.get_properties( prop )[0] # get_property_one() would be cleaner, but this works around bug #330053 except: pass if name != None: result["name"] = name break if name == None: #translators: This is used for unknown values returned by beagle #translators: for example unknown email sender, or unknown note title result["name"] = _("?") for prop, keys in beagle_type.get_extra_properties().items(): val = None for key in keys: try: val = hit.get_properties( key )[0] # get_property_one() would be cleaner, but this works around bug #330053 except: pass if val != None: result[prop] = val break if val == None: #translators: This is used for unknown values returned by beagle #translators: for example unknown email sender, or unknown note title result[prop] = _("?") def _escape_pango_markup(self, result, qstring): """ Escape everything for display through pango markup, except filenames. Filenames are escaped in escaped_uri or escaped_identifier """ for key, val in result.items(): if key == "uri" or key == "identifier": result["escaped_" + key] = cgi.escape(val) elif key == "snippet": # Add the snippet, in escaped form if available if result["snippet"] != None and result["snippet"] != "": tmp = re.sub(r"<.*?>", "", result["snippet"]) tmp = re.sub(r"</.*?>", "", tmp) result["snippet"] = cgi.escape(tmp) # FIXME: re.escape too much, we only want to escape special regex chars # we should provide a convenient method for _all_ modules result["snippet"] = re.sub( re.escape(qstring), "<span weight='bold'>" + qstring + "</span>", result["snippet"], re.IGNORECASE) else: result["snippet"] = "" elif isinstance(result[key], str): result[key] = cgi.escape(val) @staticmethod def has_requirements(): # Check if we have python bindings for beagle try: import beagle except Exception, e: BeagleLiveHandler.INSTRUCTIONS = _( "Could not load beagle, libbeagle has been compiled without python bindings." ) return False # Check if beagled is running if not beagle.beagle_util_daemon_is_running(): if is_program_in_path("beagled"): BeagleLiveHandler.INSTRUCTIONS = _( "Beagle daemon is not running.") return False else: BeagleLiveHandler.INSTRUCTIONS = _( "Beagled could not be found in your $PATH.") return False else: return True