From: fuzzyray Date: Wed, 22 Sep 2010 21:51:32 +0000 (-0000) Subject: Merge from genscripts r459: douglasjanderson X-Git-Tag: gentoolkit-0.3.0_rc11~23 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=e12c500456f3a03a45a217a1e13a732f28294289;p=gentoolkit.git Merge from genscripts r459: douglasjanderson Fixing a traceback when Query is passed an invalid atom, and merging some _incomplete_ work on has.py Merge from genscripts r454: brian.dolbec make the needed changes to fix bug 114086 in the has module. Merge from genscripts r452: douglasjanderson gentoolkit.query.Query can't subclass gentoolkit.atom.Atom because we can't control what portage.dep.Atom takes as input. Merge from genscripts r451: douglasjanderson Revert r438 because the problem it addresses can be taken care of more robustly. Merge from genscripts r449: douglasjanderson Make some modifications to fix bug #309091 Merge from genscripts r444: brian.dolbec add more help about the env_var's Merge from genscripts r443: douglasjanderson Simplify a func for ease of testing Merge from genscripts r442: brian.dolbec initial commit of a general purpose equery has module useable for nearly all the available vardb ENVIRONMENT data" Merge from genscripts r438: brian.dolbec rework the dpendencies _parser() tok == '' trap in an attempt to trap the InvalidAtom error, add '' removal from matches in query, add more detail in the error from Atom, add a trap to skirt around a null atom in the ChangeLog class. Hopefully I either solved it or have it printing out more info this time. Merge from genscripts r436: brian.dolbec fix the error in the raising of the GentoolkitInvalidAtom error, find and changethe info printed out in the error message to help track down the problem. Merge from genscripts r428: andkit Fix globbing for python-2.6.5/3.1.2 (fixes #315665) Apply the regexp only to the category instead of trying to modify the regexp to match the full package key to avoid relying on a specific layout of the regexp return by fnmatch.translate. svn path=/trunk/gentoolkit/; revision=811 --- diff --git a/pym/gentoolkit/equery/has.py b/pym/gentoolkit/equery/has.py new file mode 100644 index 0000000..e40a766 --- /dev/null +++ b/pym/gentoolkit/equery/has.py @@ -0,0 +1,220 @@ +# Copyright(c) 2009, Gentoo Foundation +# +# Licensed under the GNU General Public License, v2 or higher +# +# $Header: $ + +"""List all installed packages that match for a given ENVIRONMENT variable""" + +from __future__ import print_function + +__docformat__ = 'epytext' + +# ======= +# Imports +# ======= + +import sys +from getopt import gnu_getopt, GetoptError + +from portage import auxdbkeys + +import gentoolkit.pprinter as pp +from gentoolkit import errors +from gentoolkit.equery import format_options, mod_usage, CONFIG +from gentoolkit.package import PackageFormatter, FORMAT_TMPL_VARS +from gentoolkit.query import Query + +# ======= +# Globals +# ======= + +QUERY_OPTS = { + "in_installed": True, + "in_porttree": False, + "in_overlay": False, + "include_masked": True, + "show_progress": False, + "package_format": None, + "package_filter": None, + "env_var": None +} + +AUXDBKEYS = set(auxdbkeys) +AUXDBKEYS.difference_update(['UNUSED_0{0}'.format(x) for x in range(6)]) + +# ========= +# Functions +# ========= + +def print_help(with_description=True): + """Print description, usage and a detailed help message. + + @type with_description: bool + @param with_description: if true, print module's __doc__ string + """ + + if with_description: + print(__doc__.strip()) + print() + print(mod_usage(mod_name="has", arg="env_var [expr]")) + print() + print(pp.command("options")) + print(format_options(( + (" -h, --help", "display this help message"), + (" -I, --exclude-installed", + "exclude installed packages from search path"), + (" -o, --overlay-tree", "include overlays in search path"), + (" -p, --portage-tree", "include entire portage tree in search path"), + (" -F, --format=TMPL", "specify a custom output format"), + (" TMPL", + "a format template using (see man page):") + ))) + print(" " * 24, ', '.join(pp.emph(x) for x in FORMAT_TMPL_VARS)) + print() + print(pp.command("env_var")) + print("", ', '.join(pp.emph(x) for x in AUXDBKEYS)) + print(" other env_vars provided by eclasses may be available") + + +def query_in_env(query, env_var, pkg): + """Check if the query is in the pkg's environment.""" + + try: + if env_var in ("USE", "IUSE"): + results = set( + [x.lstrip("+-") for x in pkg.environment(env_var).split()] + ) + else: + results = set(pkg.environment(env_var).split()) + except errors.GentoolkitFatalError: + # aux_get KeyError or other unexpected result + return False + + if query in results: + return True + + return False + + +def display_pkg(query, env_var, pkg): + """Display information for a given package.""" + + if CONFIG['verbose']: + pkgstr = PackageFormatter( + pkg, + do_format=True, + custom_format=QUERY_OPTS["package_format"] + ) + else: + pkgstr = PackageFormatter( + pkg, + do_format=False, + custom_format=QUERY_OPTS["package_format"] + ) + + if (QUERY_OPTS["in_installed"] and + not QUERY_OPTS["in_porttree"] and + not QUERY_OPTS["in_overlay"]): + if not 'I' in pkgstr.location: + return False + if (QUERY_OPTS["in_porttree"] and + not QUERY_OPTS["in_overlay"]): + if not 'P' in pkgstr.location: + return False + if (QUERY_OPTS["in_overlay"] and + not QUERY_OPTS["in_porttree"]): + if not 'O' in pkgstr.location: + return False + pp.uprint(pkgstr) + + return True + + +def parse_module_options(module_opts): + """Parse module options and update QUERY_OPTS""" + + # Parse module options + opts = (x[0] for x in module_opts) + posargs = (x[1] for x in module_opts) + for opt, posarg in zip(opts, posargs): + if opt in ('-h', '--help'): + print_help() + sys.exit(0) + elif opt in ('-I', '--exclue-installed'): + QUERY_OPTS['in_installed'] = False + elif opt in ('-p', '--portage-tree'): + QUERY_OPTS['in_porttree'] = True + elif opt in ('-o', '--overlay-tree'): + QUERY_OPTS['in_overlay'] = True + elif opt in ('-F', '--format'): + QUERY_OPTS["package_format"] = posarg + elif opt in ('--package'): + QUERY_OPTS["package_filter"] = posarg + + +def main(input_args): + """Parse input and run the program""" + + short_opts = "hiIpoF:" # -i was option for default action + # --installed is no longer needed, kept for compatibility (djanderson '09) + long_opts = ('help', 'installed', 'exclude-installed', 'portage-tree', + 'overlay-tree', 'format=', 'package=') + + try: + module_opts, queries = gnu_getopt(input_args, short_opts, long_opts) + except GetoptError as err: + sys.stderr.write(pp.error("Module %s" % err)) + print() + print_help(with_description=False) + sys.exit(2) + + parse_module_options(module_opts) + + if not queries: + print_help() + sys.exit(2) + + query_scope = QUERY_OPTS['package_filter'] or '*' + matches = Query(query_scope).smart_find(**QUERY_OPTS) + matches.sort() + + # split out the first query since it is suppose to be the env_var + QUERY_OPTS['env_var'] = queries.pop(0) + env_var = QUERY_OPTS['env_var'] + + # + # Output + # + + if not queries: + if not QUERY_OPTS['package_filter']: + err = "Used ENV_VAR without match_expression or --package" + raise errors.GentoolkitFatalError(err, is_serious=False) + else: + if len(matches) > 1: + raise errors.AmbiguousPackageName(matches) + for match in matches: + env = QUERY_OPTS['env_var'] + print(match.environment(env)) + + first_run = True + got_match = False + for query in queries: + if not first_run: + print() + + if CONFIG['verbose']: + status = " * Searching for {0} {1} ... " + pp.uprint(status.format(env_var, pp.emph(query))) + + for pkg in matches: + if query_in_env(query, env_var, pkg): + display_pkg(query, env_var, pkg) + got_match = True + first_run = False + + if not got_match: + sys.exit(1) + +# vim: set ts=4 sw=4 tw=79: diff --git a/pym/gentoolkit/query.py b/pym/gentoolkit/query.py index c18d19e..9ad9017 100644 --- a/pym/gentoolkit/query.py +++ b/pym/gentoolkit/query.py @@ -27,6 +27,7 @@ from gentoolkit import CONFIG from gentoolkit import errors from gentoolkit import helpers from gentoolkit import pprinter as pp +from gentoolkit.atom import Atom from gentoolkit.cpv import CPV from gentoolkit.dbapi import PORTDB, VARDB from gentoolkit.package import Package @@ -36,7 +37,7 @@ from gentoolkit.sets import get_set_atoms, SETPREFIX # Classes # ======= -class Query(object): +class Query(CPV): """Provides common methods on a package query.""" def __init__(self, query, is_regex=False): @@ -60,6 +61,16 @@ class Query(object): self.is_regex = is_regex self.query_type = self._get_query_type() + # Name the rest of the chunks, if possible + if self.query_type != "set": + try: + atom = Atom(self.query) + self.__dict__.update(atom.__dict__) + except errors.GentoolkitInvalidAtom: + CPV.__init__(self, self.query) + self.operator = '' + self.atom = self.cpv + def __repr__(self): rx = '' if self.is_regex: @@ -79,8 +90,7 @@ class Query(object): cat_str = "" pkg_str = pp.emph(self.query) else: - cpv = CPV(self.query) - cat, pkg = cpv.category, cpv.name + cpv.fullversion + cat, pkg = self.category, self.name + self.fullversion if cat and not self.is_regex: cat_str = "in %s " % pp.emph(cat.lstrip('><=~!')) else: @@ -185,7 +195,9 @@ class Query(object): if in_installed: matches.extend(VARDB.match(self.query)) except portage.exception.InvalidAtom as err: - raise errors.GentoolkitInvalidAtom(str(err)) + message = "query.py: find(), query=%s, InvalidAtom=%s" %( + self.query, str(err)) + raise errors.GentoolkitInvalidAtom(message) return [Package(x) for x in set(matches)] @@ -221,7 +233,9 @@ class Query(object): try: best = PORTDB.xmatch("bestmatch-visible", self.query) except portage.exception.InvalidAtom as err: - raise errors.GentoolkitInvalidAtom(err) + message = "query.py: find_best(), bestmatch-visible, " + \ + "query=%s, InvalidAtom=%s" %(self.query, str(err)) + raise errors.GentoolkitInvalidAtom(message) # xmatch can return an empty string, so checking for None is not enough if not best: if not (include_keyworded or include_masked): @@ -229,7 +243,9 @@ class Query(object): try: matches = PORTDB.xmatch("match-all", self.query) except portage.exception.InvalidAtom as err: - raise errors.GentoolkitInvalidAtom(err) + message = "query.py: find_best(), match-all, query=%s, InvalidAtom=%s" %( + self.query, str(err)) + raise errors.GentoolkitInvalidAtom(message) masked = portage.best(matches) keywordable = [] for m in matches: @@ -302,10 +318,7 @@ class Query(object): cat_re = cat else: cat_re = fnmatch.translate(cat) - # [::-1] reverses a sequence, so we're emulating an ".rreplace()" - # except we have to put our "new" string on backwards - cat_re = cat_re[::-1].replace('$', '*./', 1)[::-1] - predicate = lambda x: re.match(cat_re, x) + predicate = lambda x: re.match(cat_re, x.split("/", 1)[0]) pre_filter = self.package_finder(predicate=predicate) # Post-filter