aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'gentoolkit/pym/gentoolkit/equery/uses.py')
-rw-r--r--gentoolkit/pym/gentoolkit/equery/uses.py317
1 files changed, 317 insertions, 0 deletions
diff --git a/gentoolkit/pym/gentoolkit/equery/uses.py b/gentoolkit/pym/gentoolkit/equery/uses.py
new file mode 100644
index 0000000..8358d49
--- /dev/null
+++ b/gentoolkit/pym/gentoolkit/equery/uses.py
@@ -0,0 +1,317 @@
+# Copyright(c) 2009-2010, Gentoo Foundation
+#
+# Licensed under the GNU General Public License, v2
+#
+# $Header: $
+
+"""Display USE flags for a given package"""
+
+# Move to imports section when Python 2.6 is stable
+from __future__ import with_statement
+
+__docformat__ = 'epytext'
+
+# =======
+# Imports
+# =======
+
+import os
+import sys
+from functools import partial
+from getopt import gnu_getopt, GetoptError
+from glob import glob
+
+from portage import settings
+
+import gentoolkit.pprinter as pp
+from gentoolkit import errors
+from gentoolkit.equery import format_options, mod_usage, CONFIG
+from gentoolkit.helpers import find_best_match, find_packages, uniqify
+from gentoolkit.textwrap_ import TextWrapper
+
+# =======
+# Globals
+# =======
+
+QUERY_OPTS = {"allVersions" : False}
+
+# =========
+# 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=__name__.split('.')[-1])
+ print
+ print pp.command("options")
+ print format_options((
+ (" -h, --help", "display this help message"),
+ (" -a, --all", "include all package versions")
+ ))
+
+
+def display_useflags(output):
+ """Print USE flag descriptions and statuses.
+
+ @type output: list
+ @param output: [(inuse, inused, flag, desc, restrict), ...]
+ inuse (int) = 0 or 1; if 1, flag is set in make.conf
+ inused (int) = 0 or 1; if 1, package is installed with flag enabled
+ flag (str) = the name of the USE flag
+ desc (str) = the flag's description
+ restrict (str) = corresponds to the text of restrict in metadata
+ """
+
+ maxflag_len = len(max([t[2] for t in output], key=len))
+
+ twrap = TextWrapper()
+ twrap.width = CONFIG['termWidth']
+ twrap.subsequent_indent = " " * (maxflag_len + 8)
+
+ markers = ("-", "+")
+ color = (
+ partial(pp.useflag, enabled=False), partial(pp.useflag, enabled=True)
+ )
+ for in_makeconf, in_installed, flag, desc, restrict in output:
+ if CONFIG['verbose']:
+ flag_name = ""
+ if in_makeconf != in_installed:
+ flag_name += pp.emph(" %s %s" %
+ (markers[in_makeconf], markers[in_installed]))
+ else:
+ flag_name += (" %s %s" %
+ (markers[in_makeconf], markers[in_installed]))
+
+ flag_name += " " + color[in_makeconf](flag.ljust(maxflag_len))
+ flag_name += " : "
+
+ # print description
+ if restrict:
+ restrict = "(%s %s)" % (pp.emph("Restricted to"),
+ pp.cpv(restrict))
+ twrap.initial_indent = flag_name
+ print twrap.fill(restrict)
+ if desc:
+ twrap.initial_indent = twrap.subsequent_indent
+ print twrap.fill(desc)
+ else:
+ print " : <unknown>"
+ else:
+ if desc:
+ twrap.initial_indent = flag_name
+ desc = twrap.fill(desc)
+ print desc
+ else:
+ twrap.initial_indent = flag_name
+ print twrap.fill("<unknown>")
+ else:
+ print markers[in_makeconf] + flag
+
+
+def get_global_useflags():
+ """Get global and expanded USE flag variables from
+ PORTDIR/profiles/use.desc and PORTDIR/profiles/desc/*.desc respectively.
+
+ @rtype: dict
+ @return: {'flag_name': 'flag description', ...}
+ """
+
+ global_usedesc = {}
+ # Get global USE flag descriptions
+ try:
+ path = os.path.join(settings["PORTDIR"], 'profiles', 'use.desc')
+ with open(path) as open_file:
+ for line in open_file:
+ if line.startswith('#'):
+ continue
+ # Ex. of fields: ['syslog', 'Enables support for syslog\n']
+ fields = line.split(" - ", 1)
+ if len(fields) == 2:
+ global_usedesc[fields[0]] = fields[1].rstrip()
+ except IOError:
+ sys.stderr.write(
+ pp.warn(
+ "Could not load USE flag descriptions from %s" % pp.path(path)
+ )
+ )
+
+ del path, open_file
+ # Add USE_EXPANDED variables to usedesc hash -- Bug #238005
+ for path in glob(os.path.join(settings["PORTDIR"],
+ 'profiles', 'desc', '*.desc')):
+ try:
+ with open(path) as open_file:
+ for line in open_file:
+ if line.startswith('#'):
+ continue
+ fields = [field.strip() for field in line.split(" - ", 1)]
+ if len(fields) == 2:
+ expanded_useflag = "%s_%s" % \
+ (path.split("/")[-1][0:-5], fields[0])
+ global_usedesc[expanded_useflag] = fields[1]
+ except IOError:
+ sys.stderr.write(
+ pp.warn("Could not load USE flag descriptions from %s" % path)
+ )
+
+ return global_usedesc
+
+
+def get_matches(query):
+ """Get packages matching query."""
+
+ if not QUERY_OPTS["allVersions"]:
+ matches = [find_best_match(query)]
+ if None in matches:
+ matches = find_packages(query, include_masked=False)
+ if matches:
+ matches.sort()
+ else:
+ matches = find_packages(query, include_masked=True)
+
+ if not matches:
+ raise errors.GentoolkitNoMatches(query)
+
+ return matches
+
+
+def get_output_descriptions(pkg, global_usedesc):
+ """Prepare descriptions and usage information for each USE flag."""
+
+ local_usedesc = pkg.metadata.use()
+ iuse = pkg.environment("IUSE")
+
+ if iuse:
+ usevar = uniqify([x.lstrip('+-') for x in iuse.split()])
+ usevar.sort()
+ else:
+ usevar = []
+
+ if pkg.is_installed():
+ used_flags = pkg.use().split()
+ else:
+ used_flags = settings["USE"].split()
+
+ # store (inuse, inused, flag, desc, restrict)
+ output = []
+ for flag in usevar:
+ inuse = False
+ inused = False
+
+ local_use = None
+ for use in local_usedesc:
+ if use.name == flag:
+ local_use = use
+ break
+
+ try:
+ desc = local_use.description
+ except AttributeError:
+ try:
+ desc = global_usedesc[flag]
+ except KeyError:
+ desc = ""
+
+ try:
+ restrict = local_use.restrict
+ restrict = restrict if restrict is not None else ""
+ except AttributeError:
+ restrict = ""
+
+ if flag in pkg.settings("USE").split():
+ inuse = True
+ if flag in used_flags:
+ inused = True
+
+ output.append((inuse, inused, flag, desc, restrict))
+
+ return output
+
+
+def parse_module_options(module_opts):
+ """Parse module options and update QUERY_OPTS"""
+
+ opts = (x[0] for x in module_opts)
+ for opt in opts:
+ if opt in ('-h', '--help'):
+ print_help()
+ sys.exit(0)
+ elif opt in ('-a', '--all'):
+ QUERY_OPTS['allVersions'] = True
+
+
+def print_legend():
+ """Print a legend to explain the output format."""
+
+ print "[ Legend : %s - flag is set in make.conf ]" % pp.emph("U")
+ print "[ : %s - package is installed with flag ]" % pp.emph("I")
+ print "[ Colors : %s, %s ]" % (
+ pp.useflag("set", enabled=True), pp.useflag("unset", enabled=False))
+
+
+def main(input_args):
+ """Parse input and run the program"""
+
+ short_opts = "ha"
+ long_opts = ('help', 'all')
+
+ try:
+ module_opts, queries = gnu_getopt(input_args, short_opts, long_opts)
+ except GetoptError, 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)
+
+ #
+ # Output
+ #
+
+ first_run = True
+ legend_printed = False
+ for query in queries:
+ if not first_run:
+ print
+
+ if CONFIG['verbose']:
+ print " * Searching for %s ..." % pp.pkgquery(query)
+
+ matches = get_matches(query)
+ matches.sort()
+
+ global_usedesc = get_global_useflags()
+ for pkg in matches:
+
+ output = get_output_descriptions(pkg, global_usedesc)
+ if output:
+ if CONFIG['verbose']:
+ if not legend_printed:
+ print_legend()
+ legend_printed = True
+ print (" * Found these USE flags for %s:" %
+ pp.cpv(str(pkg.cpv)))
+ print pp.emph(" U I")
+ display_useflags(output)
+ else:
+ if CONFIG['verbose']:
+ sys.stderr.write(
+ pp.warn("No USE flags found for %s" % pp.cpv(pkg.cpv))
+ )
+
+ first_run = False
+
+# vim: set ts=4 sw=4 tw=79: