-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 This patch should cover the backport of 3.0's plugin framework. Mostly needed to backport a few utils, which were stuck in portage_util.py. A few extra files ( portage_plugins and portage_modules ) were taken wholesale. Also a small addition to portage_data and portage_const was needed. After applying the patch, register_plugins.py needs an execute bit to run ;)
Please test these as well. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iQIVAwUBQ3q8DWzglR5RwbyYAQK1Hw/+Lod7ufd+TdSvTlFz2ehhUEewfW3uvJ11 5MVFS0scOfgmKpZOlCd8UzkJS6/Stiuyr3dC+EEw1YnGDbr2Luvv2y7l1JUVrm0M ogBBDb0MtFvurDg/S0fAAS91L3U5xHyC3R52MslTzwhsasjXq7oHWSxZVgN+nAvW zmOGHj5+GMtDTvd34RgdXZbM7Ja6slvBZwYYYLWKcqC3pTKpIMIUUNZ7OUuol1Wa 6RCpHklvVMUA4ooGJHJkM/E9BvMLp0p1VufHyznoX1bo2yvQSR6lEYeSlnFIEm/X ZirjieZPSbSxDZsz6SwJLa/YOOXou0lYZAn4ZRjTJ2HwrUewUdxirGKbyFriNGXe VF1ZKvTIBNvu17CmwxGDi2esdllW3pha4ioStIYfrvp9ZR5R74R6tUSNPSIIV0CZ XxleA4RRjAo5OyXHfoOr9N2dlEHVQ3F+BOWZwAlAkd3R3EdVcFhIeCTv8Wi6xuhp sl5++d+Cj8YnX/bqZlHbWm8loSjZ2gJlXvBcdjGTsvwXQbZw48l31B++HqTUIfTP NpZvS35QGvB0hVvTiHE7BkcRaZum/gFnSEnqUC6qMUWfffAJROmlaiUrvmjiT0Yc IUDloJzmwUeUGm2w0JwQ8RqezMSe4jFEq3k7LNw4vDoE43UDdrdniD84tY/zCWPg 04Ssv5ecSbU= =vXbb -----END PGP SIGNATURE-----
diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/bin/register_plugin.py ./bin/register_plugin.py --- /usr/lib/portage/bin/register_plugin.py 1969-12-31 19:00:00.000000000 -0500 +++ ./bin/register_plugin.py 2005-11-15 23:13:04.961017280 -0500 @@ -0,0 +1,81 @@ +#!/usr/bin/python +# Copyright: 2005 Gentoo Foundation +# Author(s): Brian Harring ([EMAIL PROTECTED]) +# License: GPL2 +# $Id:$ + +import portage_plugins +from portage_modules import load_attribute +import sys + +def set(ptype, magic, version, namespace): + load_attribute(namespace) + # loaded. + portage.plugins.register(ptype, magic, version, namespace, replace=True) + +def cleanse(ptype, magic, version): + portage.plugins.deregister(ptype, magic, version) + +def get_list(ptype=None): + return portage.plugins.query_plugins(ptype) + +if __name__ == "__main__": + args = sys.argv[1:] + ret = 0 + if "-l" in args: + args.pop(args.index("-l")) + if len(args) == 0: + args = [None] + for x in args: + print "querying %s" % str(x) + try: + i = get_list(x).items() + if x is not None: + i = [(x, dict(i))] + for k,v in i: + print + try: + l = max(map(lambda y: len(y), v.keys())) + 4 + print "%s => " % k + for y in v.keys(): + print "%s: %s, %s" % (y.rjust(l), v[y]["namespace"], v[y]["version"]) + except ValueError: + print "%s => no plugins found" % k + print + except Exception, e: + print "caught exception %s querying" % e + ret = 1 + elif "-s" in args: + args.pop(args.index("-s")) + if len(args) != 4: + print "need 4 args- ptype magic version namespace" + sys.exit(1) + print "registering namespace(%s) as type(%s) constant(%s), ver(%s)" % (args[3], args[0], args[1], args[2]) + set(*args) + elif "-r" in args: + args.pop(args.index("-r")) + if len(args) != 3: + print "need 3 args- ptype magic version" + sys.exit(1) + print "deregistering type(%s) constant(%s) ver(%s)" % (args[0], args[1], args[2]) + cleanse(*args) + elif "-p" in args: + args.pop(args.index("-p")) + if len(args) != 0: + print "no args allowed currently" + sys.exit(1) + for ptype, v in get_list(None).iteritems(): + for magic, vals in v.iteritems(): + print "%s -s %s %s %s %s" % (sys.argv[0], ptype, magic, vals["version"], vals["namespace"]) + else: + if "--help" not in args: + print "command required" + print + print "options available: -s, -r, -l" + print "-s ptype magic ver namespace" + print "-r ptype magic ver" + print "-l [ptype]" + print + if "--help" not in args: + sys.exit(1) + sys.exit(0) diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_const.py ./pym/portage_const.py --- /usr/lib/portage/pym/portage_const.py 2005-11-15 23:52:28.952635928 -0500 +++ ./pym/portage_const.py 2005-11-15 23:25:01.630067024 -0500 @@ -44,6 +44,7 @@ STICKIES=["KEYWORDS_ACCEPT","USE","CFLAGS","CXXFLAGS","MAKEOPTS","EXTRA_ECONF","EXTRA_EINSTALL","EXTRA_EMAKE"] EAPI = 0 +PLUGINS_DIR = "/var/lib/portage/plugins" # =========================================================================== # END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANTS -- END OF CONSTANT diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_data.py ./pym/portage_data.py --- /usr/lib/portage/pym/portage_data.py 2005-11-15 23:42:34.000000000 -0500 +++ ./pym/portage_data.py 2005-11-15 23:53:05.503079416 -0500 @@ -43,6 +43,7 @@ uid=os.getuid() wheelgid=0 +root_uid=0 if uid==0: secpass=2 diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_dep_mod.py ./pym/portage_dep_mod.py --- /usr/lib/portage/pym/portage_dep_mod.py 2005-11-15 23:52:28.954635624 -0500 +++ ./pym/portage_dep_mod.py 1969-12-31 19:00:00.000000000 -0500 @@ -1,151 +0,0 @@ -# deps.py -- Portage dependency resolution functions -# Copyright 2003-2004 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-src/portage/pym/portage_dep.py,v 1.15.2.3 2005/04/02 14:07:59 jstubbs Exp $ -cvs_id_string="$Id: portage_dep.py,v 1.15.2.3 2005/04/02 14:07:59 jstubbs Exp $"[5:-2] - -# DEPEND SYNTAX: -# -# 'use?' only affects the immediately following word! -# Nesting is the only legal way to form multiple '[!]use?' requirements. -# -# Where: 'a' and 'b' are use flags, and 'z' is a depend atom. -# -# "a? z" -- If 'a' in [use], then b is valid. -# "a? ( z )" -- Syntax with parenthesis. -# "a? b? z" -- Deprecated. -# "a? ( b? z )" -- Valid -# "a? ( b? ( z ) ) -- Valid -# - -import os,string,types,sys,copy -import portage_exception - -def strip_empty(myarr): - for x in range(len(myarr)-1, -1, -1): - if not myarr[x]: - del myarr[x] - return myarr - -def paren_reduce(mystr,tokenize=1): - "Accepts a list of strings, and converts '(' and ')' surrounded items to sub-lists" - mylist = [] - while mystr: - if ("(" not in mystr) and (")" not in mystr): - freesec = mystr - subsec = None - tail = "" - elif mystr[0] == ")": - return [mylist,mystr[1:]] - elif ("(" in mystr) and (mystr.index("(") < mystr.index(")")): - freesec,subsec = mystr.split("(",1) - subsec,tail = paren_reduce(subsec,tokenize) - else: - subsec,tail = mystr.split(")",1) - if tokenize: - subsec = strip_empty(subsec.split(" ")) - return [mylist+subsec,tail] - return mylist+[subsec],tail - mystr = tail - if freesec: - if tokenize: - mylist = mylist + strip_empty(freesec.split(" ")) - else: - mylist = mylist + [freesec] - if subsec is not None: - mylist = mylist + [subsec] - return mylist - -def use_reduce(deparray, uselist=[], masklist=[], matchall=0, excludeall=[]): - """Takes a paren_reduce'd array and reduces the use? conditionals out - leaving an array with subarrays - """ - # Quick validity checks - for x in range(1,len(deparray)): - if deparray[x] in ["||","&&"]: - if len(deparray) == x: - # Operator is the last element - raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray)) - if type(deparray[x+1]) != types.ListType: - # Operator is not followed by a list - raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray)) - if deparray and deparray[-1] and deparray[-1][-1] == "?": - # Conditional with no target - raise portage_exception.InvalidDependString("INVALID "+deparray[x]+" DEPEND STRING: "+str(deparray)) - - mydeparray = deparray[:] - rlist = [] - while mydeparray: - head = mydeparray.pop(0) - - if type(head) == types.ListType: - rlist = rlist + [use_reduce(head, uselist, masklist, matchall, excludeall)] - - else: - if head[-1] == "?": # Use reduce next group on fail. - # Pull any other use conditions and the following atom or list into a separate array - newdeparray = [head] - while isinstance(newdeparray[-1], str) and newdeparray[-1][-1] == "?": - if mydeparray: - newdeparray.append(mydeparray.pop(0)) - else: - raise ValueError, "Conditional with no target." - - # Deprecation checks - warned = 0 - if len(newdeparray[-1]) == 0: - sys.stderr.write("Note: Empty target in string. (Deprecated)\n") - warned = 1 - if len(newdeparray) != 2: - sys.stderr.write("Note: Nested use flags without parenthesis (Deprecated)\n") - warned = 1 - if warned: - sys.stderr.write(" --> "+string.join(map(str,[head]+newdeparray))+"\n") - - # Check that each flag matches - ismatch = True - for head in newdeparray[:-1]: - head = head[:-1] - if head[0] == "!": - head = head[1:] - if not matchall and head in uselist or head in excludeall: - ismatch = False - break - elif head not in masklist: - if not matchall and head not in uselist: - ismatch = False - break - else: - ismatch = False - - # If they all match, process the target - if ismatch: - target = newdeparray[-1] - if isinstance(target, list): - rlist += [use_reduce(target, uselist, masklist, matchall, excludeall)] - else: - rlist += [target] - - else: - rlist += [head] - - return rlist - - -def dep_opconvert(deplist): - """Move || and && to the beginning of the following arrays""" - # Hack in management of the weird || for dep_wordreduce, etc. - # dep_opconvert: [stuff, ["||", list, of, things]] - # At this point: [stuff, "||", [list, of, things]] - retlist = [] - x = 0 - while x != len(deplist): - if isinstance(deplist[x], list): - retlist.append(dep_opconvert(deplist[x])) - elif deplist[x] == "||" or deplist[x] == "&&": - retlist.append([deplist[x]] + dep_opconvert(deplist[x+1])) - x += 1 - else: - retlist.append(deplist[x]) - x += 1 - return retlist diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_file.py ./pym/portage_file.py --- /usr/lib/portage/pym/portage_file.py 2005-11-15 23:52:28.955635472 -0500 +++ ./pym/portage_file.py 2005-11-15 23:20:52.424951960 -0500 @@ -8,6 +8,7 @@ import portage_data import portage_exception from portage_localization import _ +import stat def normpath(mypath): newpath = os.path.normpath(mypath) @@ -48,15 +49,78 @@ os.umask(old_umask) raise portage_util.writemsg(_("Failed to chown: %(path)s to %(uid)s:%(gid)s\n") % {"path":mypath,"uid":uid,"gid":gid}) - os.umask(old_umask) - - - - - - - - - - + +def ensure_dirs(path, gid=-1, uid=-1, mode=0777, minimal=False): + """ensure dirs exist, creating as needed with (optional) gid, uid, and mode + be forewarned- if mode is specified to a mode that blocks the euid from accessing the dir, this + code *will* try to create the dir""" + + try: + st = os.stat(path) + except OSError: + base = os.path.sep + try: + um = os.umask(0) + # if the dir perms would lack +wx, we have to force it + force_temp_perms = ((mode & 0300) != 0300) + resets = [] + apath = normpath(os.path.abspath(path)) + sticky_parent = False + creating = False + + for dir in apath.split(os.path.sep): + base = os.path.join(base,dir) + try: + st = os.stat(base) + # something exists. why are we doing isdir? + if not stat.S_ISDIR(st.st_mode): + return False + + # if it's a subdir, we need +wx at least + if apath != base: + if ((st.st_mode & 0300) != 0300): + try: os.chmod(base, (st.st_mode | 0300)) + except OSError: return False + resets.append((base, st.st_mode)) + sticky_parent = (st.st_gid & stat.S_ISGID) + + except OSError: + # nothing exists. + try: + if force_temp_perms: + os.mkdir(base, 0700) + resets.append((base, mode)) + else: + os.mkdir(base, mode) + if base == apath and sticky_parent: + resets.append((base, mode)) + if gid != -1 or uid != -1: + os.chown(base, uid, gid) + except OSError: + return False + + try: + for base, m in reversed(resets): + os.chmod(base, m) + if uid != -1 or gid != -1: + os.chown(base, uid, gid) + except OSError: + return False + + finally: + os.umask(um) + return True + else: + try: + if (gid != -1 and gid != st.st_gid) or (uid != -1 and uid != st.st_uid): + os.chown(path, uid, gid) + if minimal: + if mode != (st.st_mode & mode): + os.chmod(path, st.st_mode | mode) + elif mode != (st.st_mode & 07777): + os.chmod(path, mode) + except OSError: + return False + return True + diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_locks.py ./pym/portage_locks.py --- /usr/lib/portage/pym/portage_locks.py 2005-11-15 23:52:28.955635472 -0500 +++ ./pym/portage_locks.py 2005-11-15 23:21:13.581735640 -0500 @@ -11,6 +11,7 @@ import string import time import types +import fcntl import portage_exception import portage_file import portage_util @@ -358,3 +359,91 @@ return results +class LockException(Exception): + """Base lock exception class""" + def __init__(self, path, reason): + self.path, self.reason = path, reason + +class NonExistant(LockException): + """Missing file/dir exception""" + def __init__(self, path, reason=None): + LockException.__init__(self, path, reason) + def __str__(self): + return "Lock action for '%s' failed due to not being a valid dir/file %s" % (self.path, self.reason) + +class GenericFailed(LockException): + """the fallback lock exception class- covers perms, IOError's, and general whackyness""" + def __str__(self): + return "Lock action for '%s' failed due to '%s'" % (self.path, self.reason) + + +# should the fd be left open indefinitely? +# IMO, it shouldn't, but opening/closing everytime around is expensive + +class FsLock(object): + __slots__ = ["path", "fd", "create"] + def __init__(self, path, create=False): + """path specifies the fs path for the lock + create controls whether the file will be create if the file doesn't exist + if create is true, the base dir must exist, and it will create a file + + If you want a directory yourself, create it. + """ + self.path = path + self.fd = None + self.create = create + if not create: + if not os.path.exists(path): + raise NonExistant(path) + + def _acquire_fd(self): + if self.create: + try: self.fd = os.open(self.path, os.R_OK|os.O_CREAT) + except OSError, oe: + raise GenericFailed(self.path, oe) + else: + try: self.fd = os.open(self.path, os.R_OK) + except OSError, oe: raise NonExistant(self.path, oe) + + def _enact_change(self, flags, blocking): + if self.fd == None: + self._acquire_fd() + # we do it this way, due to the fact try/except is a bit of a hit + if not blocking: + try: fcntl.flock(self.fd, flags|fcntl.LOCK_NB) + except IOError, ie: + if ie.errno == 11: + return False + raise GenericFailed(self.path, ie) + else: + fcntl.flock(self.fd, flags) + return True + + def acquire_write_lock(self, blocking=True): + """Acquire an exclusive lock + Returns True if lock is acquired, False if not. + Note if you have a read lock, it implicitly upgrades atomically""" + return self._enact_change(fcntl.LOCK_EX, blocking) + + def acquire_read_lock(self, blocking=True): + """Acquire a shared lock + Returns True if lock is acquired, False if not. + Note, if you have a write_lock already, it'll implicitly downgrade atomically""" + return self._enact_change(fcntl.LOCK_SH, blocking) + + def release_write_lock(self): + """Release an exclusive lock if held""" + self._enact_change(fcntl.LOCK_UN, False) + + def release_read_lock(self): + self._enact_change(fcntl.LOCK_UN, False) + + def __del__(self): + # alright, it's 5:45am, yes this is weird code. + try: + if self.fd != None: + self.release_read_lock() + finally: + if self.fd != None: + os.close(self.fd) + diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_modules.py ./pym/portage_modules.py --- /usr/lib/portage/pym/portage_modules.py 1969-12-31 19:00:00.000000000 -0500 +++ ./pym/portage_modules.py 2005-11-15 23:18:15.086870984 -0500 @@ -0,0 +1,52 @@ +# Copyright: 2005 Gentoo Foundation +# License: GPL2 +# $Id: modules.py 2284 2005-11-10 00:35:50Z ferringb $ + +import sys, threading + +class FailedImport(ImportError): + def __init__(self, trg, e): self.trg, self.e = trg, e + def __str__(self): return "Failed importing target '%s': '%s'" % (self.trg, self.e) + +__import_lock = threading.Lock() + +def load_module(name): + """load a module, throwing a FailedImport if __import__ fails""" + __import_lock.acquire() + try: + if name in sys.modules: + return sys.modules[name] + try: + m = __import__(name) + nl = name.split('.') + # __import__ returns nl[0]... so. + nl.pop(0) + while len(nl): + m = getattr(m, nl[0]) + nl.pop(0) + return m + # * ferringb|afk hit it at some point, sure of that + # but no idea how, so commenting out to see if things break... + # except AttributeError, e: + # raise FailedImport(name, e) + except ImportError, e: + try: + del sys.modules[name] + except KeyError: + pass + raise FailedImport(name, e) + finally: + __import_lock.release() + +def load_attribute(name): + """load a specific attribute, rather then a module""" + try: + i = name.rfind(".") + if i == -1: + raise ValueError("name isn't an attribute, it's a module... : %s" % name) + m = load_module(name[:i]) + m = getattr(m, name[i+1:]) + return m + except (AttributeError, ImportError), e: + raise FailedImport(name, e) + diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_plugins.py ./pym/portage_plugins.py --- /usr/lib/portage/pym/portage_plugins.py 1969-12-31 19:00:00.000000000 -0500 +++ ./pym/portage_plugins.py 2005-11-15 23:51:02.883720392 -0500 @@ -0,0 +1,174 @@ +# Copyright: 2005 Gentoo Foundation +# License: GPL2 +# $Id:$ + +# I don't like this. +# doesn't seem clean/right. + +import os +from portage_const import PLUGINS_DIR +from portage_locks import FsLock, NonExistant +from portage_file import ensure_dirs +from portage_data import portage_gid, root_uid +from ConfigParser import RawConfigParser +from portage_modules import load_attribute + + +PLUGINS_EXTENSION = ".plugins" + +class RegistrationException(Exception): + def __init__(self, reason): self.reason = reason + def __str__(self): return "failed action due to %s" % self.reason + +class FailedDir(RegistrationException): + pass + +class PluginExistsAlready(RegistrationException): + def __init__(self): + RegistrationException.__init__(self, "plugin exists aleady, magic found") + +class FailedUpdating(RegistrationException): + def __str__(self): + return "failed updating plugin_type due error: %s" % (self.reason) + +class PluginNotFound(RegistrationException): + def __init__(self, plugin, reason="unknown"): + self.plugin, self.reason = plugin, reason + def __str__(self): + return "Plugin '%s' wasn't found; reason: %s" % (self.plugin, self.reason) + + +class GlobalPluginRegistry(object): + def register(self, plugin_type, magic, version, namespace, replace=False): + """register a plugin + plugin_type is a string, the category of the plugin + magic is a string, magic constant of the plugin + version is the specific plugin version (only one can be installed at a time) + namespace is the pythonic namespace for that plugin + replace controls whether or not a plugin_type + magic conflict will be replaced, or error out""" + if not ensure_dirs(PLUGINS_DIR, uid=root_uid, gid=portage_gid, mode=0755): + raise FailedDir("Failed ensuring base plugins dir") + + # this could be fine grained down to per plugin_type + plug_lock = FsLock(plugins_dir) + plug_lock.acquire_write_lock() + try: + ptype_fp = os.path.join(plugins_dir, plugin_type.lstrip(os.path.sep) + PLUGINS_EXTENSION) + existing = self.query_plugins(plugin_type, locking=False, raw=True) + if existing.has_section(magic): + if not replace: + raise PluginExistsAlready() + existing.remove_section(magic) + existing.add_section(magic) + existing.set(magic, "version", version) + existing.set(magic, "namespace", namespace) + try: + f = open(ptype_fp, "w") + os.chmod(ptype_fp, 0644) + os.chown(ptype_fp, root_uid, portage_gid) + existing.write(f) + f.close() + except OSError, oe: + raise FailedUpdating(oe) + + finally: + plug_lock.release_write_lock() + + def deregister(self, plugin_type, magic, version, ignore_errors=False): + """plugin_type is the categorization of the plugin + magic is the magic constant for lookup + version is the version of the plugin to yank + ignore_errors controls whether or not an exception is thrown when the plugin isn't found""" + plug_lock = FsLock(plugins_dir) + plug_lock.acquire_write_lock() + try: + ptype_fp = os.path.join(plugins_dir, plugin_type.lstrip(os.path.sep) + PLUGINS_EXTENSION) + existing = self.query_plugins(locking=False, raw=True) + if plugin_type not in existing: + if ignore_errors: return + raise PluginNotFound(magic, "no plugin type") + + existing = existing[plugin_type] + if not existing.has_section(magic): + if ignore_errors: return + raise PluginNotFound(magic, "magic not found in plugin_type") + + if not existing.has_option(magic, "version") or str(version) != existing.get(magic, "version"): + if ignore_errors: return + raise PluginNotFound(magic, "version not found in plugin_type") + + existing.remove_section(magic) + try: + if len(existing.sections()) == 0: + os.unlink(ptype_fp) + else: + f = open(ptype_fp, "w") + os.chmod(ptype_fp, 0644) + os.chown(ptype_fp, root_uid, portage_gid) + existing.write(f) + f.close() + except OSError, oe: + raise FailedUpdating(oe) + + finally: + plug_lock.release_write_lock() + + def get_plugin(self, plugin_type, magic): + try: address = self.query_plugins(plugin_type)[magic]["namespace"] + except KeyError: + raise PluginNotFound(magic) + return load_attribute(address) + + def query_plugins(self, plugin_type=None, locking=True, raw=False): + # designed this way to minimize lock holding time. + if plugin_type != None: + ptypes = [plugin_type + PLUGINS_EXTENSION] + d = {} + if locking: + try: + plug_lock = FsLock(plugins_dir) + except NonExistant: + return {} + plug_lock.acquire_read_lock() + try: + if plugin_type == None: + ptypes = [x for x in os.listdir(plugins_dir) if x.endswith(PLUGINS_EXTENSION) ] + + len_exten = len(PLUGINS_EXTENSION) + for x in ptypes: + c = RawConfigParser() + c.read(os.path.join(plugins_dir, x.lstrip(os.path.sep))) + if raw: + d[x[:-len_exten]] = c + else: + d[x[:-len_exten]] = dict([(y, dict(c.items(y))) for y in c.sections()]) + + finally: + if locking: + plug_lock.release_read_lock() + if plugin_type != None: + return d[plugin_type] + return d + + +registry = None +from portage.util.currying import pre_curry, pretty_docs + +def proxy_it(method, *a, **kw): + global registry + if registry == None: + registry = GlobalPluginRegistry() + return getattr(registry, method)(*a, **kw) + +for x in ["register", "deregister", "query_plugins", "get_plugin"]: + v = pre_curry(proxy_it, x) + doc = getattr(GlobalPluginRegistry, x).__doc__ + if doc == None: + doc = '' + else: + # do this so indentation on pydoc __doc__ is sane + doc = "\n".join(map(lambda x:x.lstrip(), doc.split("\n"))) +"\n" + doc += "proxied call to module level registry instances %s method" % x + globals()[x] = pretty_docs(v, doc) + +del x, v, proxy_it, doc diff -Nru --exclude portage-plugins-backport.patch --exclude '*.pyc' --exclude '*.pyo' /usr/lib/portage/pym/portage_util.py ./pym/portage_util.py --- /usr/lib/portage/pym/portage_util.py 2005-11-15 23:52:28.957635168 -0500 +++ ./pym/portage_util.py 2005-11-15 23:13:18.016032616 -0500 @@ -5,10 +5,9 @@ import sys,string,shlex,os.path -noiselimit = 0 def writemsg(mystr,noiselevel=0): """Prints out warning and debug messages based on the noiselimit setting""" - global noiselimit + noiselimit = 0 if noiselevel <= noiselimit: sys.stderr.write(mystr) sys.stderr.flush() @@ -274,8 +273,8 @@ return mykeys #cache expansions of constant strings -cexpand={} def varexpand(mystring,mydict={}): + cexpand={} try: return cexpand[" "+mystring] except KeyError: