diff options
author | fuzzyray <fuzzyray@gentoo.org> | 2008-08-27 21:19:40 +0000 |
---|---|---|
committer | fuzzyray <fuzzyray@gentoo.org> | 2008-08-27 21:19:40 +0000 |
commit | ba72586710a700ed76f35d365c645d5108bc5895 (patch) | |
tree | c16903693f2030c7b01b346b29b265dc1a473888 /src/gentoolkit | |
parent | Fix has_key() deprecation message. (Bug #232797) (diff) | |
download | gentoolkit-ba72586710a700ed76f35d365c645d5108bc5895.tar.gz gentoolkit-ba72586710a700ed76f35d365c645d5108bc5895.tar.bz2 gentoolkit-ba72586710a700ed76f35d365c645d5108bc5895.zip |
Create the gentoolkit-0.2.4 branch to coincide with the release of gentoolkit-0.2.4
svn path=/branches/gentoolkit-0.2.4/; revision=510
Diffstat (limited to 'src/gentoolkit')
-rw-r--r-- | src/gentoolkit/AUTHORS | 2 | ||||
-rw-r--r-- | src/gentoolkit/Makefile | 22 | ||||
-rw-r--r-- | src/gentoolkit/README | 17 | ||||
-rw-r--r-- | src/gentoolkit/TODO | 0 | ||||
-rw-r--r-- | src/gentoolkit/__init__.py | 59 | ||||
-rw-r--r-- | src/gentoolkit/errors.py | 14 | ||||
-rw-r--r-- | src/gentoolkit/helpers.py | 162 | ||||
-rw-r--r-- | src/gentoolkit/package.py | 241 | ||||
-rw-r--r-- | src/gentoolkit/pprinter.py | 116 |
9 files changed, 633 insertions, 0 deletions
diff --git a/src/gentoolkit/AUTHORS b/src/gentoolkit/AUTHORS new file mode 100644 index 0000000..0dfa694 --- /dev/null +++ b/src/gentoolkit/AUTHORS @@ -0,0 +1,2 @@ +Original author: +Karl Trygve Kalleberg <karltk@gentoo.org>
\ No newline at end of file diff --git a/src/gentoolkit/Makefile b/src/gentoolkit/Makefile new file mode 100644 index 0000000..831bcfd --- /dev/null +++ b/src/gentoolkit/Makefile @@ -0,0 +1,22 @@ +# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> +# Copyright 2004 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# +# $Header$ + +include ../../makedefs.mak + +all: + echo "LISTOWEL (n.) The small mat on the bar designed to be more absorbent than the bar, but not as absorbent as your elbows." + +dist: + mkdir -p ../../${distdir}/src/gentoolkit + cp Makefile AUTHORS README TODO errors.py package.py helpers.py pprinter.py __init__.py ../../${distdir}/src/gentoolkit/ + +install: + install -d $(docdir)/gentoolkit + install -m 0644 AUTHORS README TODO $(docdir)/gentoolkit/ + install -d $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit + install -m 0644 package.py pprinter.py helpers.py errors.py $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit/ + install -m 0644 __init__.py $(DESTDIR)/usr/lib/gentoolkit/pym/gentoolkit/ + diff --git a/src/gentoolkit/README b/src/gentoolkit/README new file mode 100644 index 0000000..916dc81 --- /dev/null +++ b/src/gentoolkit/README @@ -0,0 +1,17 @@ + +Package : gentoolkit +Version : see __init__.py +Author : See AUTHORS + +MOTIVATION + +This is the Python API for Gentoolkit. It contains common functionality shared +by the Gentoolkit tools written in Python. + +MECHANICS + +N/A + +IMPROVEMENTS + +N/A diff --git a/src/gentoolkit/TODO b/src/gentoolkit/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/gentoolkit/TODO diff --git a/src/gentoolkit/__init__.py b/src/gentoolkit/__init__.py new file mode 100644 index 0000000..28b56be --- /dev/null +++ b/src/gentoolkit/__init__.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# +# Copyright 2003-2004 Karl Trygve Kalleberg +# Copyright 2003-2004 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# +# $Header$ +# Author: Karl Trygve Kalleberg <karltk@gentoo.org> +# +# Portions written ripped from +# - etcat, by Alistair Tse <liquidx@gentoo.org> +# + +__author__ = "Karl Trygve Kalleberg" +__email__ = "karltk@gentoo.org" +__version__ = "0.1.1" +__productname__ = "gentoolkit" +__description__ = "Gentoolkit Common Library" + +import os +import sys +try: + import portage +except ImportError: + sys.path.insert(0, "/usr/lib/portage/pym") + import portage +import re +try: + from threading import Lock +except ImportError: + # If we don't have thread support, we don't need to worry about + # locking the global settings object. So we define a "null" Lock. + class Lock: + def acquire(self): + pass + def release(self): + pass + +try: + import portage.exception as portage_exception +except ImportError: + import portage_exception + +try: + settingslock = Lock() + settings = portage.config(clone=portage.settings) + porttree = portage.db[portage.root]["porttree"] + vartree = portage.db[portage.root]["vartree"] + virtuals = portage.db[portage.root]["virtuals"] +except portage_exception.PermissionDenied, e: + sys.stderr.write("Permission denied: '%s'\n" % str(e)) + sys.exit(e.errno) + +Config = { + "verbosityLevel": 3 +} + +from helpers import * +from package import * diff --git a/src/gentoolkit/errors.py b/src/gentoolkit/errors.py new file mode 100644 index 0000000..db81721 --- /dev/null +++ b/src/gentoolkit/errors.py @@ -0,0 +1,14 @@ +#! /usr/bin/python2 +# +# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> +# Copyright(c) 2004, Gentoo Foundation +# +# Licensed under the GNU General Public License, v2 +# +# $Header$ + +class FatalError: + def __init__(self, s): + self._message = s + def get_message(self): + return self._message
\ No newline at end of file diff --git a/src/gentoolkit/helpers.py b/src/gentoolkit/helpers.py new file mode 100644 index 0000000..bf2b1b1 --- /dev/null +++ b/src/gentoolkit/helpers.py @@ -0,0 +1,162 @@ +#!/usr/bin/python2 +# +# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> +# Copyright(c) 2004, Gentoo Foundation +# +# Licensed under the GNU General Public License, v2 +# +# $Header$ + +import portage +from gentoolkit import * +from package import * +from pprinter import print_warn +try: + from portage.util import unique_array +except ImportError: + from portage_util import unique_array + +def find_packages(search_key, masked=False): + """Returns a list of Package objects that matched the search key.""" + try: + if masked: + t = portage.db["/"]["porttree"].dbapi.xmatch("match-all", search_key) + t += portage.db["/"]["vartree"].dbapi.match(search_key) + else: + t = portage.db["/"]["porttree"].dbapi.match(search_key) + t += portage.db["/"]["vartree"].dbapi.match(search_key) + # catch the "amgigous package" Exception + except ValueError, e: + if isinstance(e[0],list): + t = [] + for cp in e[0]: + if masked: + t += portage.db["/"]["porttree"].dbapi.xmatch("match-all", cp) + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + t += portage.db["/"]["porttree"].dbapi.match(cp) + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + raise ValueError(e) + except portage_exception.InvalidAtom, e: + print_warn("Invalid Atom: '%s'" % str(e)) + return [] + # Make the list of packages unique + t = unique_array(t) + t.sort() + return [Package(x) for x in t] + +def find_installed_packages(search_key, masked=False): + """Returns a list of Package objects that matched the search key.""" + try: + t = portage.db["/"]["vartree"].dbapi.match(search_key) + # catch the "amgigous package" Exception + except ValueError, e: + if isinstance(e[0],list): + t = [] + for cp in e[0]: + t += portage.db["/"]["vartree"].dbapi.match(cp) + else: + raise ValueError(e) + except portage_exception.InvalidAtom, e: + print_warn("Invalid Atom: '%s'" % str(e)) + return [] + return [Package(x) for x in t] + +def find_best_match(search_key): + """Returns a Package object for the best available installed candidate that + matched the search key.""" + t = portage.db["/"]["vartree"].dep_bestmatch(search_key) + if t: + return Package(t) + return None + +def find_system_packages(prefilter=None): + """Returns a tuple of lists, first list is resolved system packages, + second is a list of unresolved packages.""" + pkglist = settings.packages + resolved = [] + unresolved = [] + for x in pkglist: + cpv = x.strip() + if len(cpv) and cpv[0] == "*": + pkg = find_best_match(cpv) + if pkg: + resolved.append(pkg) + else: + unresolved.append(cpv) + return (resolved, unresolved) + +def find_world_packages(prefilter=None): + """Returns a tuple of lists, first list is resolved world packages, + seond is unresolved package names.""" + f = open(portage.root+portage.WORLD_FILE) + pkglist = f.readlines() + resolved = [] + unresolved = [] + for x in pkglist: + cpv = x.strip() + if len(cpv) and cpv[0] != "#": + pkg = find_best_match(cpv) + if pkg: + resolved.append(pkg) + else: + unresolved.append(cpv) + return (resolved,unresolved) + +def find_all_installed_packages(prefilter=None): + """Returns a list of all installed packages, after applying the prefilter + function""" + t = vartree.dbapi.cpv_all() + if prefilter: + t = filter(prefilter,t) + return [Package(x) for x in t] + +def find_all_uninstalled_packages(prefilter=None): + """Returns a list of all uninstalled packages, after applying the prefilter + function""" + alist = find_all_packages(prefilter) + return [x for x in alist if not x.is_installed()] + +def find_all_packages(prefilter=None): + """Returns a list of all known packages, installed or not, after applying + the prefilter function""" + t = porttree.dbapi.cp_all() + t += vartree.dbapi.cp_all() + if prefilter: + t = filter(prefilter,t) + t = unique_array(t) + t2 = [] + for x in t: + t2 += porttree.dbapi.cp_list(x) + t2 += vartree.dbapi.cp_list(x) + t2 = unique_array(t2) + return [Package(x) for x in t2] + +def split_package_name(name): + """Returns a list on the form [category, name, version, revision]. Revision will + be 'r0' if none can be inferred. Category and version will be empty, if none can + be inferred.""" + r = portage.catpkgsplit(name) + if not r: + r = name.split("/") + if len(r) == 1: + return ["", name, "", "r0"] + else: + return r + ["", "r0"] + else: + r = list(r) + if r[0] == 'null': + r[0] = '' + return r + +def sort_package_list(pkglist): + """Returns the list ordered in the same way portage would do with lowest version + at the head of the list.""" + pkglist.sort(Package.compare_version) + return pkglist + +if __name__ == "__main__": + print "This module is for import only" + + diff --git a/src/gentoolkit/package.py b/src/gentoolkit/package.py new file mode 100644 index 0000000..3319860 --- /dev/null +++ b/src/gentoolkit/package.py @@ -0,0 +1,241 @@ +#! /usr/bin/python2 +# +# Copyright(c) 2004, Karl Trygve Kalleberg <karltk@gentoo.org> +# Copyright(c) 2004, Gentoo Foundation +# +# Licensed under the GNU General Public License, v2 +# +# $Header$ + +from errors import FatalError +import portage +from gentoolkit import * + +class Package: + """Package descriptor. Contains convenience functions for querying the + state of a package, its contents, name manipulation, ebuild info and + similar.""" + + def __init__(self,cpv): + self._cpv = cpv + self._scpv = portage.catpkgsplit(self._cpv) + + if not self._scpv: + raise FatalError("invalid cpv: %s" % cpv) + self._db = None + self._settings = settings + self._settingslock = settingslock + + def get_name(self): + """Returns base name of package, no category nor version""" + return self._scpv[1] + + def get_version(self): + """Returns version of package, with revision number""" + v = self._scpv[2] + if self._scpv[3] != "r0": + v += "-" + self._scpv[3] + return v + + def get_category(self): + """Returns category of package""" + return self._scpv[0] + + def get_settings(self, key): + """Returns the value of the given key for this package (useful + for package.* files.""" + self._settingslock.acquire() + self._settings.setcpv(self._cpv) + v = self._settings[key] + self._settingslock.release() + return v + + def get_cpv(self): + """Returns full Category/Package-Version string""" + return self._cpv + + def get_provide(self): + """Return a list of provides, if any""" + if not self.is_installed(): + try: + x = [self.get_env_var('PROVIDE')] + except KeyError: + x = [] + return x + else: + return vartree.get_provide(self._cpv) + + def get_dependants(self): + """Retrieves a list of CPVs for all packages depending on this one""" + raise NotImplementedError("Not implemented yet!") + + def get_runtime_deps(self): + """Returns a linearised list of first-level run time dependencies for this package, on + the form [(comparator, [use flags], cpv), ...]""" + # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies + try: + cd = self.get_env_var("RDEPEND", porttree).split() + except KeyError: + cd = self.get_env_var("RDEPEND", vartree).split() + r,i = self._parse_deps(cd) + return r + + def get_compiletime_deps(self): + """Returns a linearised list of first-level compile time dependencies for this package, on + the form [(comparator, [use flags], cpv), ...]""" + # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies + try: + rd = self.get_env_var("DEPEND", porttree).split() + except KeyError: + rd = self.get_env_var("DEPEND", vartree).split() + r,i = self._parse_deps(rd) + return r + + def get_postmerge_deps(self): + """Returns a linearised list of first-level post merge dependencies for this package, on + the form [(comparator, [use flags], cpv), ...]""" + # Try to use the portage tree first, since emerge only uses the tree when calculating dependencies + try: + pd = self.get_env_var("PDEPEND", porttree).split() + except KeyError: + pd = self.get_env_var("PDEPEND", vartree).split() + r,i = self._parse_deps(pd) + return r + + def _parse_deps(self,deps,curuse=[],level=0): + # store (comparator, [use predicates], cpv) + r = [] + comparators = ["~","<",">","=","<=",">="] + end = len(deps) + i = 0 + while i < end: + tok = deps[i] + if tok == ')': + return r,i + if tok[-1] == "?": + tok = tok.replace("?","") + sr,l = self._parse_deps(deps[i+2:],curuse=curuse+[tok],level=level+1) + r += sr + i += l + 3 + continue + if tok == "||": + sr,l = self._parse_deps(deps[i+2:],curuse,level=level+1) + r += sr + i += l + 3 + continue + # conjonction, like in "|| ( ( foo bar ) baz )" => recurse + if tok == "(": + sr,l = self._parse_deps(deps[i+1:],curuse,level=level+1) + r += sr + i += l + 2 + continue + # pkg block "!foo/bar" => ignore it + if tok[0] == "!": + i += 1 + continue + # pick out comparator, if any + cmp = "" + for c in comparators: + if tok.find(c) == 0: + cmp = c + tok = tok[len(cmp):] + r.append((cmp,curuse,tok)) + i += 1 + return r,i + + def is_installed(self): + """Returns true if this package is installed (merged)""" + self._initdb() + return os.path.exists(self._db.getpath()) + + def is_overlay(self): + """Returns true if the package is in an overlay.""" + dir,ovl = portage.portdb.findname2(self._cpv) + return ovl != settings["PORTDIR"] + + def is_masked(self): + """Returns true if this package is masked against installation. Note: We blindly assume that + the package actually exists on disk somewhere.""" + unmasked = portage.portdb.xmatch("match-visible", "=" + self._cpv) + return self._cpv not in unmasked + + def get_ebuild_path(self,in_vartree=0): + """Returns the complete path to the .ebuild file""" + if in_vartree: + return vartree.getebuildpath(self._cpv) + else: + return portage.portdb.findname(self._cpv) + + def get_package_path(self): + """Returns the path to where the ChangeLog, Manifest, .ebuild files reside""" + p = self.get_ebuild_path() + sp = p.split("/") + if len(sp): + return "/".join(sp[:-1]) + + def get_env_var(self, var, tree=""): + """Returns one of the predefined env vars DEPEND, RDEPEND, SRC_URI,....""" + if tree == "": + mytree = vartree + if not self.is_installed(): + mytree = porttree + else: + mytree = tree + r = mytree.dbapi.aux_get(self._cpv,[var]) + if not r: + raise FatalError("Could not find the package tree") + if len(r) != 1: + raise FatalError("Should only get one element!") + return r[0] + + def get_use_flags(self): + """Returns the USE flags active at time of installation""" + self._initdb() + if self.is_installed(): + return self._db.getfile("USE") + return "" + + def get_contents(self): + """Returns the full contents, as a dictionary, on the form + [ '/bin/foo' : [ 'obj', '1052505381', '45ca8b8975d5094cd75bdc61e9933691' ], ... ]""" + self._initdb() + if self.is_installed(): + return self._db.getcontents() + return {} + + def compare_version(self,other): + """Compares this package's version to another's CPV; returns -1, 0, 1""" + v1 = self._scpv + v2 = portage.catpkgsplit(other.get_cpv()) + # if category is different + if v1[0] != v2[0]: + return cmp(v1[0],v2[0]) + # if name is different + elif v1[1] != v2[1]: + return cmp(v1[1],v2[1]) + # Compare versions + else: + return portage.pkgcmp(v1[1:],v2[1:]) + + def size(self): + """Estimates the installed size of the contents of this package, if possible. + Returns [size, number of files in total, number of uncounted files]""" + contents = self.get_contents() + size = 0 + uncounted = 0 + files = 0 + for x in contents: + try: + size += os.lstat(x).st_size + files += 1 + except OSError: + uncounted += 1 + return [size, files, uncounted] + + def _initdb(self): + """Internal helper function; loads package information from disk, + when necessary""" + if not self._db: + cat = self.get_category() + pnv = self.get_name()+"-"+self.get_version() + self._db = portage.dblink(cat,pnv,settings["ROOT"],settings) diff --git a/src/gentoolkit/pprinter.py b/src/gentoolkit/pprinter.py new file mode 100644 index 0000000..39665f8 --- /dev/null +++ b/src/gentoolkit/pprinter.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +# +# Copyright 2004 Karl Trygve Kalleberg <karltk@gentoo.org> +# Copyright 2004 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# +# $Header$ + +import sys +import gentoolkit + +try: + import portage.output as output +except ImportError: + import output + + +def print_error(s): + """Prints an error string to stderr.""" + sys.stderr.write(output.red("!!! ") + s + "\n") + +def print_info(lv, s, line_break = True): + """Prints an informational string to stdout.""" + if gentoolkit.Config["verbosityLevel"] >= lv: + sys.stdout.write(s) + if line_break: + sys.stdout.write("\n") + +def print_warn(s): + """Print a warning string to stderr.""" + sys.stderr.write("!!! " + s + "\n") + +def die(err, s): + """Print an error string and die with an error code.""" + print_error(s) + sys.exit(-err) + +# Colour settings + +def cpv(s): + """Print a category/package-<version> string.""" + return output.green(s) + +def slot(s): + """Print a slot string""" + return output.bold(s) + +def useflag(s): + """Print a USE flag strign""" + return output.blue(s) + +def useflagon(s): + """Print an enabled USE flag string""" + # FIXME: Collapse into useflag with parameter + return output.red(s) + +def useflagoff(s): + """Print a disabled USE flag string""" + # FIXME: Collapse into useflag with parameter + return output.blue(s) + +def maskflag(s): + """Print a masking flag string""" + return output.red(s) + +def installedflag(s): + """Print an installed flag string""" + return output.bold(s) + +def number(s): + """Print a number string""" + return output.turquoise(s) + +def pkgquery(s): + """Print a package query string.""" + return output.bold(s) + +def regexpquery(s): + """Print a regular expression string""" + return output.bold(s) + +def path(s): + """Print a file or directory path string""" + return output.bold(s) + +def path_symlink(s): + """Print a symlink string.""" + return output.turquoise(s) + +def productname(s): + """Print a product name string, i.e. the program name.""" + return output.turquoise(s) + +def globaloption(s): + """Print a global option string, i.e. the program global options.""" + return output.yellow(s) + +def localoption(s): + """Print a local option string, i.e. the program local options.""" + return output.green(s) + +def command(s): + """Print a program command string.""" + return output.green(s) + +def section(s): + """Print a string as a section header.""" + return output.turquoise(s) + +def subsection(s): + """Print a string as a subsection header.""" + return output.turquoise(s) + +def emph(s): + """Print a string as emphasized.""" + return output.bold(s) |