From 000102587bf416600c5e3a83f293d5225505367f Mon Sep 17 00:00:00 2001 From: fuzzyray Date: Wed, 9 Dec 2009 19:07:50 +0000 Subject: [PATCH] helpers2.py has been move to helpers.py and helpers.py has been moved to deprecated/helpers.py svn path=/trunk/gentoolkit/; revision=707 --- pym/gentoolkit/helpers2.py | 437 ------------------------------------- 1 file changed, 437 deletions(-) delete mode 100644 pym/gentoolkit/helpers2.py diff --git a/pym/gentoolkit/helpers2.py b/pym/gentoolkit/helpers2.py deleted file mode 100644 index f9d0c49..0000000 --- a/pym/gentoolkit/helpers2.py +++ /dev/null @@ -1,437 +0,0 @@ -# Copyright(c) 2009, Gentoo Foundation -# -# Licensed under the GNU General Public License, v2 or higher - -"""Improved versions of the original helpers functions. - -As a convention, functions ending in '_packages' or '_match{es}' return -Package objects, while functions ending in 'cpvs' return a sequence of strings. -Functions starting with 'get_' return a set of packages by default and can be -filtered, while functions starting with 'find_' return nothing unless the -query matches one or more packages. - -This should be merged into helpers when a clean path is found. -""" - -# Move to Imports section after Python 2.6 is stable -from __future__ import with_statement - -__all__ = ( - 'compare_package_strings', - 'do_lookup', - 'find_best_match', - 'find_installed_packages', - 'find_packages', - 'get_cpvs', - 'get_installed_cpvs', - 'get_uninstalled_cpvs', - 'uses_globbing' -) -__author__ = 'Douglas Anderson' -__docformat__ = 'epytext' - -# ======= -# Imports -# ======= - -import re -import fnmatch -from functools import partial - -import portage -from portage.util import unique_array - -import gentoolkit -import gentoolkit.pprinter as pp -from gentoolkit import Config, PORTDB, VARDB -from gentoolkit import errors -from gentoolkit.package import Package - -# ========= -# Functions -# ========= - -def compare_package_strings(pkg1, pkg2): - """Similar to the builtin cmp, but for package strings. Usually called - as: package_list.sort(compare_package_strings) - - An alternative is to use the Package descriptor from gentoolkit.package - >>> pkgs = [Package(x) for x in package_list] - >>> pkgs.sort() - - @see: >>> help(cmp) - """ - - pkg1 = portage.versions.catpkgsplit(pkg1) - pkg2 = portage.versions.catpkgsplit(pkg2) - # Compare categories - if pkg1[0] != pkg2[0]: - return cmp(pkg1[0], pkg2[0]) - # Compare names - elif pkg1[1] != pkg2[1]: - return cmp(pkg1[1], pkg2[1]) - # Compare versions - else: - return portage.versions.pkgcmp(pkg1[1:], pkg2[1:]) - - -def do_lookup(query, query_opts): - """A high-level wrapper around gentoolkit package-finder functions. - - @type query: str - @param query: pkg, cat/pkg, pkg-ver, cat/pkg-ver, atom or regex - @type query_opts: dict - @param query_opts: user-configurable options from the calling module - Currently supported options are: - - categoryFilter = str or None - includeInstalled = bool - includePortTree = bool - includeOverlayTree = bool - isRegex = bool - printMatchInfo = bool # Print info about the search - - @rtype: list - @return: Package objects matching query - """ - - if query_opts["includeInstalled"]: - if query_opts["includePortTree"] or query_opts["includeOverlayTree"]: - simple_package_finder = partial(find_packages, include_masked=True) - complex_package_finder = get_cpvs - else: - simple_package_finder = find_installed_packages - complex_package_finder = get_installed_cpvs - elif query_opts["includePortTree"] or query_opts["includeOverlayTree"]: - simple_package_finder = partial(find_packages, include_masked=True) - complex_package_finder = get_uninstalled_cpvs - else: - pp.die(2, "Not searching in installed, portage tree or overlay." - " Nothing to do.") - - is_simple_query = True - if query_opts["isRegex"] or uses_globbing(query): - is_simple_query = False - - if is_simple_query: - matches = _do_simple_lookup(query, simple_package_finder, query_opts) - else: - matches = _do_complex_lookup(query, complex_package_finder, query_opts) - - return matches - - -def _do_complex_lookup(query, package_finder, query_opts): - """Find matches for a query which is a regex or includes globbing.""" - - # pylint: Too many branches (18/12) - # pylint: disable-message=R0912 - result = [] - - if query_opts["printMatchInfo"] and not Config["piping"]: - print_query_info(query, query_opts) - - cats = prepare_categories(query_opts["categoryFilter"]) - cat = split_query(query)[0] - - pre_filter = [] - # The "get_" functions can pre-filter against the whole package key, - # but since we allow globbing now, we run into issues like: - # >>> portage.dep.dep_getkey("sys-apps/portage-*") - # 'sys-apps/portage-' - # So the only way to guarantee we don't overrun the key is to - # prefilter by cat only. - if cats: - pre_filter = package_finder(predicate=lambda x: x.startswith(cats)) - if cat: - if query_opts["isRegex"]: - 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) - if pre_filter: - pre_filter = [x for x in pre_filter if predicate(x)] - else: - pre_filter = package_finder(predicate=predicate) - - # Post-filter - if query_opts["isRegex"]: - predicate = lambda x: re.match(query, x) - else: - if cat: - query_re = fnmatch.translate(query) - else: - query_re = fnmatch.translate("*/%s" % query) - predicate = lambda x: re.search(query_re, x) - if pre_filter: - result = [x for x in pre_filter if predicate(x)] - else: - result = package_finder(predicate=predicate) - - return [Package(x) for x in result] - - -def _do_simple_lookup(query, package_finder, query_opts): - """Find matches for a query which is an atom or string.""" - - result = [] - - cats = prepare_categories(query_opts["categoryFilter"]) - if query_opts["printMatchInfo"] and not Config["piping"]: - print_query_info(query, query_opts) - - result = package_finder(query) - if not query_opts["includeInstalled"]: - result = [x for x in result if not x.is_installed()] - - if cats: - result = [x for x in result if x.cpv.startswith(cats)] - - return result - - -def find_best_match(query): - """Return the highest unmasked version of a package matching query. - - @type query: str - @param query: can be of the form: pkg, pkg-ver, cat/pkg, cat/pkg-ver, atom - @rtype: str or None - """ - - match = PORTDB.xmatch("bestmatch-visible", query) - - return Package(match) if match else None - - -def find_installed_packages(query): - """Return a list of Package objects that matched the search key.""" - - try: - matches = VARDB.match(query) - # catch the ambiguous package Exception - except portage.exception.AmbiguousPackageName, err: - matches = [] - for pkgkey in err[0]: - matches.extend(VARDB.match(pkgkey)) - except portage.exception.InvalidAtom, err: - pp.print_warn("Invalid Atom: '%s'" % str(err)) - return [] - - return [Package(x) for x in matches] - - -def find_packages(query, include_masked=False): - """Returns a list of Package objects that matched the query. - - @type query: str - @param query: can be of the form: pkg, pkg-ver, cat/pkg, cat/pkg-ver, atom - @rtype: list - @return: matching Package objects - """ - - if not query: - return [] - - try: - if include_masked: - matches = PORTDB.xmatch("match-all", query) - else: - matches = PORTDB.match(query) - matches.extend(VARDB.match(query)) - except portage.exception.InvalidAtom, err: - raise errors.GentoolkitInvalidAtom(str(err)) - - return [Package(x) for x in unique_array(matches)] - - -def get_cpvs(predicate=None, include_installed=True): - """Get all packages in the Portage tree and overlays. Optionally apply a - predicate. - - Example usage: - >>> from gentoolkit.helpers2 import get_cpvs - >>> len(get_cpvs()) - 26065 - >>> fn = lambda x: x.startswith('app-portage') - >>> len(get_cpvs(fn, include_installed=False)) - 112 - - @type predicate: function - @param predicate: a function to filter the package list with - @type include_installed: bool - @param include_installed: - If True: Return the union of all_cpvs and all_installed_cpvs - If False: Return the difference of all_cpvs and all_installed_cpvs - @rtype: list - @return: ['cat/portdir_pkg-1', 'cat/overlay_pkg-2', ...] - """ - - if predicate: - all_cps = [x for x in PORTDB.cp_all() if predicate(x)] - else: - all_cps = PORTDB.cp_all() - - all_cpvs = [] - for pkgkey in all_cps: - all_cpvs.extend(PORTDB.cp_list(pkgkey)) - - result = set(all_cpvs) - all_installed_cpvs = get_installed_cpvs(predicate) - - if include_installed: - result.update(all_installed_cpvs) - else: - result.difference_update(all_installed_cpvs) - - return list(result) - - -# pylint thinks this is a global variable -# pylint: disable-msg=C0103 -get_uninstalled_cpvs = partial(get_cpvs, include_installed=False) - - -def get_installed_cpvs(predicate=None): - """Get all installed packages. Optionally apply a predicate. - - @type predicate: function - @param predicate: a function to filter the package list with - @rtype: unsorted list - @return: ['cat/installed_pkg-1', 'cat/installed_pkg-2', ...] - """ - - if predicate: - all_installed_cps = [x for x in VARDB.cp_all() if predicate(x)] - else: - all_installed_cps = VARDB.cp_all() - - result = [] - for pkgkey in all_installed_cps: - result.extend(VARDB.cp_list(pkgkey)) - - return list(result) - - -def prepare_categories(category_filter): - """Return a tuple of validated categories. Expand globs. - - Example usage: - >>> prepare_categories('app-portage,sys-apps') - ('app-portage', 'sys-apps') - """ - - if not category_filter: - return tuple() - - cats = [x.lstrip('=') for x in category_filter.split(',')] - valid_cats = portage.settings.categories - good_cats = [] - for cat in cats: - if set('!*?[]').intersection(set(cat)): - good_cats.extend(fnmatch.filter(valid_cats, cat)) - elif cat in valid_cats: - good_cats.append(cat) - else: - raise errors.GentoolkitInvalidCategory(cat) - - return tuple(good_cats) - - -def print_query_info(query, query_opts): - """Print info about the query to the screen.""" - - cats = prepare_categories(query_opts["categoryFilter"]) - cat, pkg, ver, rev = split_query(query) - del ver, rev - if cats: - cat_str = "in %s " % ', '.join([pp.emph(x) for x in cats]) - elif cat and not query_opts["isRegex"]: - cat_str = "in %s " % pp.emph(cat) - else: - cat_str = "" - - if query_opts["isRegex"]: - pkg_str = query - else: - pkg_str = pkg - - print " * Searching for %s %s..." % (pp.emph(pkg_str), cat_str) - - -def print_file(path): - """Display the contents of a file.""" - - with open(path) as open_file: - lines = open_file.read() - print lines.strip() - - -def print_sequence(seq): - """Print every item of a sequence.""" - - for item in seq: - print item - - -def split_query(query): - """Split a query into category, name, version and revision. - - @type query: str - @param query: pkg, cat/pkg, pkg-ver, cat/pkg-ver, atom or regex - @rtype: tuple - @return: (category, pkg_name, version, revision) - Each tuple element is a string or empty string (""). - """ - - result = portage.versions.catpkgsplit(query) - - if result: - result = list(result) - if result[0] == 'null': - result[0] = '' - if result[3] == 'r0': - result[3] = '' - else: - result = query.split("/") - if len(result) == 1: - result = ['', query, '', ''] - else: - result = result + ['', ''] - - if len(result) != 4: - pp.print_error("Too many slashes ('/').") - raise errors.GentoolkitInvalidPackageName(query) - - return tuple(result) - - -def uniqify(seq, preserve_order=True): - """Return a uniqified list. Optionally preserve order.""" - - if preserve_order: - seen = set() - result = [x for x in seq if x not in seen and not seen.add(x)] - else: - result = list(set(seq)) - - return result - - -def uses_globbing(query): - """Check the query to see if it is using globbing. - - @rtype: bool - @return: True if query uses globbing, else False - """ - - if set('!*?[]').intersection(set(query)): - if portage.dep.get_operator(query): - # Query may be an atom such as '=sys-apps/portage-2.2*' - pass - else: - return True - - return False -- 2.26.2