__slots__ = ("fetch_all", "pkg", "pretend", "settings")
def execute(self):
+ settings = self.settings
+ pkg = self.pkg
+ portdb = pkg.root_config.trees["porttree"].dbapi
+ ebuild_path = portdb.findname(pkg.cpv)
+ settings.setcpv(pkg)
+ debug = settings.get("PORTAGE_DEBUG") == "1"
+ use_cache = 1 # always true
+ portage.doebuild_environment(ebuild_path, "fetch",
+ settings["ROOT"], settings, debug, use_cache, portdb)
+ restrict_fetch = 'fetch' in settings['PORTAGE_RESTRICT'].split()
+
+ if restrict_fetch:
+ rval = self._execute_with_builddir()
+ else:
+ rval = portage.doebuild(ebuild_path, "fetch",
+ settings["ROOT"], settings, debug=debug,
+ listonly=self.pretend, fetchonly=1, fetchall=self.fetch_all,
+ mydbapi=portdb, tree="porttree")
+
+ if rval != os.EX_OK:
+ msg = "Fetch failed for '%s'" % (pkg.cpv,)
+ eerror(msg, phase="unpack", key=pkg.cpv)
+
+ return rval
+
+ def _execute_with_builddir(self):
# To spawn pkg_nofetch requires PORTAGE_BUILDDIR for
# ensuring sane $PWD (bug #239560) and storing elog
# messages. Use a private temp directory, in order
root_config = pkg.root_config
portdb = root_config.trees["porttree"].dbapi
ebuild_path = portdb.findname(pkg.cpv)
- settings.setcpv(pkg)
debug = settings.get("PORTAGE_DEBUG") == "1"
- use_cache = 1 # always true
- portage.doebuild_environment(ebuild_path, "fetch",
- root_config.root, settings, debug, use_cache, portdb)
portage.prepare_build_dirs(self.pkg.root, self.settings, 0)
retval = portage.doebuild(ebuild_path, "fetch",
# portage.py -- core Portage functionality
-# Copyright 1998-2004 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
try:
from portage.cache.cache_errors import CacheError
- import portage.util as util
- util.lazy_import(globals(),
+ import portage.proxy.lazyimport
+ import portage.proxy as proxy
+ proxy.lazyimport.lazyimport(globals(),
'portage.checksum',
'portage.checksum:perform_checksum,perform_md5,prelink_capable',
'portage.cvstree',
'portage.update:dep_transform,fixdbentries,grab_updates,' + \
'parse_updates,update_config_files,update_dbentries,' + \
'update_dbentry',
+ 'portage.util',
+ 'portage.util:atomic_ofstream,apply_secpass_permissions,' + \
+ 'apply_recursive_permissions,dump_traceback,getconfig,' + \
+ 'grabdict,grabdict_package,grabfile,grabfile_package,' + \
+ 'map_dictlist_vals,new_protect_filename,normalize_path,' + \
+ 'pickle_read,pickle_write,stack_dictlist,stack_dicts,' + \
+ 'stack_lists,unique_array,varexpand,writedict,writemsg,' + \
+ 'writemsg_stdout,write_atomic',
+ 'portage.versions',
'portage.versions:best,catpkgsplit,catsplit,endversion_keys,' + \
'suffix_value@endversion,pkgcmp,pkgsplit,vercmp,ververify',
'portage.xpak',
from portage.data import ostype, lchown, userland, secpass, uid, wheelgid, \
portage_uid, portage_gid, userpriv_groups
from portage.manifest import Manifest
-
- from portage.util import atomic_ofstream, apply_secpass_permissions, apply_recursive_permissions, \
- dump_traceback, getconfig, grabdict, grabdict_package, grabfile, grabfile_package, \
- map_dictlist_vals, new_protect_filename, normalize_path, \
- pickle_read, pickle_write, stack_dictlist, stack_dicts, stack_lists, \
- unique_array, varexpand, writedict, writemsg, writemsg_stdout, write_atomic
import portage.exception
from portage.localization import _
#parse /etc/env.d and generate /etc/profile.env
def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
- env=None, writemsg_level=portage.util.writemsg_level):
+ env=None, writemsg_level=None):
+ if writemsg_level is None:
+ writemsg_level = portage.util.writemsg_level
if target_root is None:
global settings
target_root = settings["ROOT"]
if not isinstance(test, config):
raise TypeError("Invalid type for config object: %s (should be %s)" % (test.__class__, config))
+def _lazy_iuse_regex(iuse_implicit):
+ """
+ The PORTAGE_IUSE value is lazily evaluated since re.escape() is slow
+ and the value is only used when an ebuild phase needs to be executed
+ (it's used only to generate QA notices).
+ """
+ # Escape anything except ".*" which is supposed to pass through from
+ # _get_implicit_iuse().
+ regex = sorted(re.escape(x) for x in iuse_implicit)
+ regex = "^(%s)$" % "|".join(regex)
+ regex = regex.replace("\\.\\*", ".*")
+ return regex
+
class config(object):
"""
This class encompasses the main portage configuration. Data is pulled from
self.configlist.append(self.mygcfg)
self.configdict["conf"]=self.configlist[-1]
- self.configlist.append({})
+ self.configlist.append(util.LazyItemsDict())
self.configdict["pkg"]=self.configlist[-1]
#auto-use:
iuse_implicit = self._get_implicit_iuse()
iuse_implicit.update(x.lstrip("+-") for x in iuse.split())
- # Escape anything except ".*" which is supposed
- # to pass through from _get_implicit_iuse()
- regex = sorted(re.escape(x) for x in iuse_implicit)
- regex = "^(%s)$" % "|".join(regex)
- regex = regex.replace("\\.\\*", ".*")
- self.configdict["pkg"]["PORTAGE_IUSE"] = regex
+ # PORTAGE_IUSE is not always needed so it's lazily evaluated.
+ self.configdict["pkg"].addLazySingleton(
+ "PORTAGE_IUSE", _lazy_iuse_regex, iuse_implicit)
ebuild_force_test = self.get("EBUILD_FORCE_TEST") == "1"
if ebuild_force_test and \
return 1
_prepare_workdir(mysettings)
- _prepare_features_dirs(mysettings)
+ if mysettings.get('EBUILD_PHASE') != 'fetch':
+ # Avoid spurious permissions adjustments when fetching with
+ # a temporary PORTAGE_TMPDIR setting (for fetchonly).
+ _prepare_features_dirs(mysettings)
def _adjust_perms_msg(settings, msg):
atexit_register(portageexit)
+def _ensure_default_encoding():
+ """
+ The python that's inside stage 1 or 2 is built with a minimal
+ configuration which does not include the /usr/lib/pythonX.Y/encodings
+ directory. This results in error like the following:
+
+ LookupError: no codec search functions registered: can't find encoding
+
+ In order to solve this problem, detect it early and manually register
+ a search function for the ascii codec. Starting with python-3.0 this
+ problem is more noticeable because of stricter handling of encoding
+ and decoding between strings of characters and bytes.
+ """
+
+ import codecs
+ try:
+ codecs.lookup(sys.getdefaultencoding())
+ except LookupError:
+ pass
+ else:
+ return
+
+ class IncrementalEncoder(codecs.IncrementalEncoder):
+ def encode(self, input, final=False):
+ return codecs.ascii_encode(input, self.errors)[0]
+
+ class IncrementalDecoder(codecs.IncrementalDecoder):
+ def decode(self, input, final=False):
+ return codecs.ascii_decode(input, self.errors)[0]
+
+ class StreamWriter(codecs.StreamWriter):
+ encode = codecs.ascii_encode
+
+ class StreamReader(codecs.StreamReader):
+ decode = codecs.ascii_decode
+
+ # The sys.setdefaultencoding() function doesn't necessarily exist,
+ # so just setup the ascii codec to correspond to whatever name
+ # happens to be returned by sys.getdefaultencoding().
+ encoding = sys.getdefaultencoding()
+
+ def search_function(name):
+ if name != encoding:
+ return None
+ return codecs.CodecInfo(
+ name=encoding,
+ encode=codecs.ascii_encode,
+ decode=codecs.ascii_decode,
+ incrementalencoder=IncrementalEncoder,
+ incrementaldecoder=IncrementalDecoder,
+ streamwriter=StreamWriter,
+ streamreader=StreamReader,
+ )
+
+ codecs.register(search_function)
+
def _global_updates(trees, prev_mtimes):
"""
Perform new global updates if they exist in $PORTDIR/profiles/updates/.
myroots.append((settings["ROOT"], settings))
for myroot, mysettings in myroots:
- trees[myroot] = portage.util.LazyItemsDict(trees.get(myroot, None))
+ trees[myroot] = portage.util.LazyItemsDict(trees.get(myroot, {}))
trees[myroot].addLazySingleton("virtuals", mysettings.getvirtuals, myroot)
trees[myroot].addLazySingleton(
"vartree", vartree, myroot, categories=mysettings.categories,
binarytree, myroot, mysettings["PKGDIR"], settings=mysettings)
return trees
-class _LegacyGlobalProxy(portage.util.ObjectProxy):
+class _LegacyGlobalProxy(proxy.objectproxy.ObjectProxy):
"""
Instances of these serve as proxies to global variables
that are initialized on demand.
"""
def __init__(self, name):
- portage.util.ObjectProxy.__init__(self)
+ proxy.objectproxy.ObjectProxy.__init__(self)
object.__setattr__(self, '_name', name)
def _get_target(self):
name = object.__getattribute__(self, '_name')
return globals()[name]
-class _PortdbProxy(portage.util.ObjectProxy):
+class _PortdbProxy(proxy.objectproxy.ObjectProxy):
"""
The portdb is initialized separately from the rest
of the variables, since sometimes the other variables
_portdb_initialized = True
return portdb
-class _MtimedbProxy(portage.util.ObjectProxy):
+class _MtimedbProxy(proxy.objectproxy.ObjectProxy):
"""
The mtimedb is independent from the portdb and other globals.
"""
def __init__(self, name):
- portage.util.ObjectProxy.__init__(self)
+ proxy.objectproxy.ObjectProxy.__init__(self)
object.__setattr__(self, '_name', name)
def _get_target(self):
"flushmtimedb"):
globals()[k] = _LegacyGlobalProxy(k)
+ _ensure_default_encoding()
+
# Clear the cache
dircache={}
http://bugs.python.org/issue2876
"""
- def __init__(self, dict=None, **kwargs):
- self.data = {}
- if dict is not None:
- self.update(dict)
+ def __init__(self, *args, **kwargs):
+
+ if len(args) > 1:
+ raise TypeError(
+ "expected at most 1 positional argument, got " + \
+ repr(len(args)))
+
+ if args:
+ self.update(args[0])
+
if kwargs:
self.update(kwargs)
# data.py -- Calculated/Discovered Data Values
-# Copyright 1998-2004 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
import os, sys, pwd, grp, platform
-from portage.util import writemsg
from portage.const import rootuid, portageuser, portagegroup, EPREFIX
-from portage.output import colorize
-from portage.output import create_color_func
-bad = create_color_func("BAD")
+
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.output:colorize',
+ 'portage.util:writemsg',
+)
ostype=platform.system()
userland = None
lchown()
def portage_group_warning():
- warn_prefix = bad("*** WARNING *** ")
+ warn_prefix = colorize("BAD", "*** WARNING *** ")
mylines = [
"For security reasons, only system administrators should be",
"allowed in the portage group. Untrusted users or processes",
-# Copyright 1998-2007 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
import os
import re
-from portage.dep import match_from_list
-from portage.locks import unlockfile
-from portage.output import colorize
-from portage.util import writemsg, cmp_sort_key
-from portage import auxdbkeys, dep_expand
-from portage.versions import catpkgsplit, pkgcmp
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.dep:match_from_list',
+ 'portage.locks:unlockfile',
+ 'portage.output:colorize',
+ 'portage.util:cmp_sort_key,writemsg',
+ 'portage.versions:catpkgsplit,pkgcmp',
+)
+
+from portage import auxdbkeys, dep_expand
class dbapi(object):
_category_re = re.compile(r'^\w[-.+\w]*$')
-# Copyright 1998-2007 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
__all__ = ["bindbapi", "binarytree"]
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.dep:dep_getkey,isjustname,isvalidatom,match_from_list',
+ 'portage.output:EOutput,colorize',
+ 'portage.update:update_dbentries',
+ 'portage.util:ensure_dirs,normalize_path,writemsg,writemsg_stdout',
+ 'portage.versions:best,catpkgsplit,catsplit',
+)
+
from portage.cache.mappings import slot_dict_class
-from portage.dep import isvalidatom, isjustname, dep_getkey, match_from_list
from portage.dbapi.virtual import fakedbapi
from portage.exception import InvalidPackageName, \
PermissionDenied, PortageException
-from portage.output import EOutput, colorize
-from portage.util import ensure_dirs, normalize_path, writemsg, writemsg_stdout
-from portage.versions import best, catpkgsplit, catsplit
-from portage.update import update_dbentries
from portage.const import EAPI, EAPIPREFIX
from portage import dep_expand, listdir, _check_distfile, _movefile
-import portage
-
import os, errno, stat
import re
from itertools import chain, izip
-# Copyright 1998-2007 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
__all__ = ["portdbapi", "close_portdbapi_caches", "portagetree"]
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.checksum',
+ 'portage.dep:dep_getkey,match_from_list,paren_reduce,use_reduce',
+ 'portage.util:ensure_dirs,writemsg',
+ 'portage.versions:best,catpkgsplit,pkgsplit,ver_regexp',
+)
+
from portage.cache.cache_errors import CacheError
from portage.cache.mappings import slot_dict_class
from portage.const import REPO_NAME_LOC
from portage.data import portage_gid, secpass
from portage.dbapi import dbapi
-from portage.dep import use_reduce, paren_reduce, dep_getkey, match_from_list
from portage.exception import PortageException, \
FileNotFound, InvalidDependString, InvalidPackageName
from portage.manifest import Manifest
-from portage.util import ensure_dirs, writemsg
-from portage.versions import pkgsplit, catpkgsplit, best, ver_regexp
-
-import portage.checksum
from portage import eclass_cache, auxdbkeys, doebuild, flatten, \
listdir, dep_expand, eapi_is_supported, key_expand, dep_check, \
-# Copyright 1998-2007 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
"vardbapi", "vartree", "dblink"] + \
["write_contents", "tar_contents"]
-from portage.checksum import perform_md5
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.checksum:perform_md5',
+ 'portage.dep:dep_getkey,isjustname,isvalidatom,match_from_list,' + \
+ 'use_reduce,paren_reduce',
+ 'portage.elog:elog_process',
+ 'portage.elog.filtering:filter_mergephases,filter_unmergephases',
+ 'portage.locks:lockdir,unlockdir',
+ 'portage.output:bold,colorize',
+ 'portage.update:fixdbentries',
+ 'portage.util:apply_secpass_permissions,ConfigProtect,ensure_dirs,' + \
+ 'writemsg,writemsg_level,write_atomic,atomic_ofstream,writedict,' + \
+ 'grabfile,grabdict,normalize_path,new_protect_filename,getlibpaths',
+ 'portage.versions:best,catpkgsplit,catsplit,pkgcmp,pkgsplit',
+)
+
from portage.const import CACHE_PATH, CONFIG_MEMORY_FILE, \
PORTAGE_PACKAGE_ATOM, PRIVATE_PATH, VDB_PATH, EPREFIX, EPREFIX_LSTRIP
from portage.data import portage_gid, portage_uid, secpass, ostype
from portage.dbapi import dbapi
-from portage.dep import use_reduce, paren_reduce, isvalidatom, \
- isjustname, dep_getkey, match_from_list
from portage.exception import CommandNotFound, \
InvalidData, InvalidPackageName, \
FileNotFound, PermissionDenied, UnsupportedAPIException
-from portage.locks import lockdir, unlockdir
-from portage.output import bold, colorize
-from portage.update import fixdbentries
-from portage.util import apply_secpass_permissions, ConfigProtect, ensure_dirs, \
- writemsg, writemsg_level, write_atomic, atomic_ofstream, writedict, \
- grabfile, grabdict, normalize_path, new_protect_filename, getlibpaths
-from portage.versions import pkgsplit, catpkgsplit, catsplit, best, pkgcmp
from portage import listdir, dep_expand, digraph, flatten, key_expand, \
doebuild_environment, doebuild, env_update, prepare_build_dirs, \
abssymlink, movefile, _movefile, bsd_chflags, cpv_getkey
-from portage.elog import elog_process
-from portage.elog.filtering import filter_mergephases, filter_unmergephases
from portage.cache.mappings import slot_dict_class
import os, re, shutil, stat, errno, copy, subprocess
# elog/__init__.py - elog core functions
-# Copyright 2006-2007 Gentoo Foundation
+# Copyright 2006-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.util:writemsg',
+)
+
from portage.const import EBUILD_PHASES
from portage.exception import PortageException
from portage.process import atexit_register
-from portage.util import writemsg
-
from portage.elog.messages import collect_ebuild_messages, collect_messages
from portage.elog.filtering import filter_loglevels
# elog/messages.py - elog core functions
-# Copyright 2006-2007 Gentoo Foundation
+# Copyright 2006-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
-from portage.output import colorize
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.output:colorize',
+ 'portage.util:writemsg',
+)
+
from portage.const import EBUILD_PHASES
-from portage.util import writemsg
import os
import sys
-# Copyright 1999-2006 Gentoo Foundation
+# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
import errno, os
-import portage.versions, portage.const
-from portage.checksum import *
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.checksum:hashfunc_map,perform_multiple_checksums,verify_all',
+ 'portage.util:write_atomic',
+)
+
from portage.exception import *
-from portage.util import write_atomic
class FileNotInManifestException(PortageException):
pass
-# Copyright 1998-2004 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
import re
import shlex
import sys
+
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.util:writemsg',
+)
+
from portage.const import COLOR_MAP_FILE, EPREFIX
-from portage.util import writemsg
from portage.exception import CommandNotFound, FileNotFound, \
ParseError, PermissionDenied, PortageException
# portage.py -- core Portage functionality
-# Copyright 1998-2004 Gentoo Foundation
+# Copyright 1998-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
import signal
import sys
-from portage.util import dump_traceback
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.util:dump_traceback',
+)
+
from portage.const import BASH_BINARY, SANDBOX_BINARY, FAKEROOT_BINARY
from portage.exception import CommandNotFound
--- /dev/null
+# Copyright 2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
--- /dev/null
+# Copyright 2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['lazyimport']
+
+import sys
+import types
+
+try:
+ import threading
+except ImportError:
+ import dummy_threading as threading
+
+from portage.proxy.objectproxy import ObjectProxy
+
+_module_proxies = {}
+_module_proxies_lock = threading.RLock()
+
+def _register_module_proxy(name, proxy):
+ _module_proxies_lock.acquire()
+ try:
+ proxy_list = _module_proxies.get(name)
+ if proxy_list is None:
+ proxy_list = []
+ _module_proxies[name] = proxy_list
+ proxy_list.append(proxy)
+ finally:
+ _module_proxies_lock.release()
+
+def _unregister_module_proxy(name):
+ """
+ Destroy all proxies that reference the give module name. Also, check
+ for other proxies referenced by modules that have been imported and
+ destroy those proxies too. This way, destruction of a single proxy
+ can trigger destruction of all the rest.
+ """
+ _module_proxies_lock.acquire()
+ try:
+ proxy_list = _module_proxies.get(name)
+ if proxy_list is not None:
+ # First delete this name from the dict so that
+ # if this same thread reenters below, it won't
+ # enter this path again.
+ del _module_proxies[name]
+ for proxy in proxy_list:
+ object.__getattribute__(proxy, '_get_target')()
+
+ modules = sys.modules
+ for name, proxy_list in list(_module_proxies.iteritems()):
+ if name not in modules:
+ continue
+ # First delete this name from the dict so that
+ # if this same thread reenters below, it won't
+ # enter this path again.
+ del _module_proxies[name]
+ for proxy in proxy_list:
+ object.__getattribute__(proxy, '_get_target')()
+ finally:
+ _module_proxies_lock.release()
+
+class _LazyImport(ObjectProxy):
+
+ __slots__ = ('_scope', '_alias', '_name', '_target')
+
+ def __init__(self, scope, alias, name):
+ ObjectProxy.__init__(self)
+ object.__setattr__(self, '_scope', scope)
+ object.__setattr__(self, '_alias', alias)
+ object.__setattr__(self, '_name', name)
+ _register_module_proxy(name, self)
+
+ def _get_target(self):
+ try:
+ return object.__getattribute__(self, '_target')
+ except AttributeError:
+ pass
+ name = object.__getattribute__(self, '_name')
+ __import__(name)
+ target = sys.modules[name]
+ object.__setattr__(self, '_target', target)
+ object.__getattribute__(self, '_scope')[
+ object.__getattribute__(self, '_alias')] = target
+ _unregister_module_proxy(name)
+ return target
+
+class _LazyImportFrom(_LazyImport):
+
+ __slots__ = ('_attr_name',)
+
+ def __init__(self, scope, name, attr_name, alias):
+ object.__setattr__(self, '_attr_name', attr_name)
+ _LazyImport.__init__(self, scope, alias, name)
+
+ def _get_target(self):
+ try:
+ return object.__getattribute__(self, '_target')
+ except AttributeError:
+ pass
+ name = object.__getattribute__(self, '_name')
+ attr_name = object.__getattribute__(self, '_attr_name')
+ __import__(name)
+ target = getattr(sys.modules[name], attr_name)
+ object.__setattr__(self, '_target', target)
+ object.__getattribute__(self, '_scope')[
+ object.__getattribute__(self, '_alias')] = target
+ _unregister_module_proxy(name)
+ return target
+
+def lazyimport(scope, *args):
+ """
+ Create a proxy in the given scope in order to performa a lazy import.
+
+ Syntax Result
+ foo import foo
+ foo:bar,baz from foo import bar, baz
+ foo:bar@baz from foo import bar as baz
+
+ @param scope: the scope in which to place the import, typically globals()
+ @type myfilename: dict
+ @param args: module names to import
+ @type args: strings
+ """
+
+ modules = sys.modules
+
+ for s in args:
+ parts = s.split(':', 1)
+ if len(parts) == 1:
+ name = s
+
+ if not name or not isinstance(name, basestring):
+ raise ValueError(name)
+
+ components = name.split('.')
+ parent_scope = scope
+ for i in xrange(len(components)):
+ alias = components[i]
+ if i < len(components) - 1:
+ parent_name = ".".join(components[:i+1])
+ __import__(parent_name)
+ mod = modules.get(parent_name)
+ if not isinstance(mod, types.ModuleType):
+ # raise an exception
+ __import__(name)
+ parent_scope[alias] = mod
+ parent_scope = mod.__dict__
+ continue
+
+ already_imported = modules.get(name)
+ if already_imported is not None:
+ parent_scope[alias] = already_imported
+ else:
+ parent_scope[alias] = \
+ _LazyImport(parent_scope, alias, name)
+
+ else:
+ name, fromlist = parts
+ already_imported = modules.get(name)
+ fromlist = fromlist.split(',')
+ for s in fromlist:
+ alias = s.split('@', 1)
+ if len(alias) == 1:
+ alias = alias[0]
+ attr_name = alias
+ else:
+ attr_name, alias = alias
+ if already_imported is not None:
+ try:
+ scope[alias] = getattr(already_imported, attr_name)
+ except AttributeError:
+ raise ImportError('cannot import name %s' % attr_name)
+ else:
+ scope[alias] = \
+ _LazyImportFrom(scope, name, attr_name, alias)
--- /dev/null
+# Copyright 2008-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+__all__ = ['ObjectProxy']
+
+class ObjectProxy(object):
+
+ """
+ Object that acts as a proxy to another object, forwarding
+ attribute accesses and method calls. This can be useful
+ for implementing lazy initialization.
+ """
+
+ __slots__ = ()
+
+ def _get_target(self):
+ raise NotImplementedError(self)
+
+ def __getattribute__(self, attr):
+ result = object.__getattribute__(self, '_get_target')()
+ return getattr(result, attr)
+
+ def __setattr__(self, attr, value):
+ result = object.__getattribute__(self, '_get_target')()
+ setattr(result, attr, value)
+
+ def __call__(self, *args, **kwargs):
+ result = object.__getattribute__(self, '_get_target')()
+ return result(*args, **kwargs)
+
+ def __setitem__(self, key, value):
+ object.__getattribute__(self, '_get_target')()[key] = value
+
+ def __getitem__(self, key):
+ return object.__getattribute__(self, '_get_target')()[key]
+
+ def __delitem__(self, key):
+ del object.__getattribute__(self, '_get_target')()[key]
+
+ def __contains__(self, key):
+ return key in object.__getattribute__(self, '_get_target')()
+
+ def __iter__(self):
+ return iter(object.__getattribute__(self, '_get_target')())
+
+ def __len__(self):
+ return len(object.__getattribute__(self, '_get_target')())
+
+ def __repr__(self):
+ return repr(object.__getattribute__(self, '_get_target')())
+
+ def __str__(self):
+ return str(object.__getattribute__(self, '_get_target')())
+
+ def __hash__(self):
+ return hash(object.__getattribute__(self, '_get_target')())
+
+ def __eq__(self, other):
+ return object.__getattribute__(self, '_get_target')() == other
+
+ def __ne__(self, other):
+ return object.__getattribute__(self, '_get_target')() != other
+
+ def __nonzero__(self):
+ return bool(object.__getattribute__(self, '_get_target')())
-# Copyright 1999-2006 Gentoo Foundation
+# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
import errno, os, re, sys
-from portage.util import ConfigProtect, grabfile, new_protect_filename, \
- normalize_path, write_atomic, writemsg
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+ 'portage.dep:dep_getkey,get_operator,isvalidatom,isjustname,remove_slot',
+ 'portage.util:ConfigProtect,grabfile,new_protect_filename,' + \
+ 'normalize_path,write_atomic,writemsg',
+ 'portage.versions:ververify'
+)
+
from portage.exception import DirectoryNotFound, PortageException
-from portage.versions import ververify
-from portage.dep import dep_getkey, get_operator, isvalidatom, isjustname, \
- remove_slot
from portage.const import USER_CONFIG_PATH, WORLD_FILE
ignored_dbentries = ("CONTENTS", "environment.bz2")
-# Copyright 2004 Gentoo Foundation
+# Copyright 2004-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
+__all__ = ['apply_permissions', 'apply_recursive_permissions',
+ 'apply_secpass_permissions', 'apply_stat_permissions', 'atomic_ofstream',
+ 'cmp_sort_key', 'ConfigProtect', 'dump_traceback', 'ensure_dirs',
+ 'getconfig', 'getlibpaths', 'grabdict', 'grabdict_package', 'grabfile',
+ 'grabfile_package', 'grablines', 'initialize_logger', 'LazyItemsDict',
+ 'map_dictlist_vals', 'new_protect_filename', 'normalize_path',
+ 'pickle_read', 'stack_dictlist', 'stack_dicts', 'stack_lists',
+ 'unique_array', 'varexpand', 'write_atomic', 'writedict', 'writemsg',
+ 'writemsg_level', 'writemsg_stdout']
import os
import errno
OperationNotPermitted, PermissionDenied, ReadOnlyFileSystem
import portage.exception
from portage.dep import isvalidatom
+from portage.proxy.objectproxy import ObjectProxy
from portage.const import EPREFIX, EPREFIX_LSTRIP
try:
return 0
return 1
-class ObjectProxy(object):
-
- """
- Object that acts as a proxy to another object, forwarding
- attribute accesses and method calls. This can be useful
- for implementing lazy initialization.
- """
-
- __slots__ = ()
-
- def _get_target(self):
- raise NotImplementedError(self)
-
- def __getattribute__(self, attr):
- result = object.__getattribute__(self, '_get_target')()
- return getattr(result, attr)
-
- def __setattr__(self, attr, value):
- result = object.__getattribute__(self, '_get_target')()
- setattr(result, attr, value)
-
- def __call__(self, *args, **kwargs):
- result = object.__getattribute__(self, '_get_target')()
- return result(*args, **kwargs)
-
- def __setitem__(self, key, value):
- object.__getattribute__(self, '_get_target')()[key] = value
-
- def __getitem__(self, key):
- return object.__getattribute__(self, '_get_target')()[key]
-
- def __delitem__(self, key):
- del object.__getattribute__(self, '_get_target')()[key]
-
- def __contains__(self, key):
- return key in object.__getattribute__(self, '_get_target')()
-
- def __iter__(self):
- return iter(object.__getattribute__(self, '_get_target')())
-
- def __len__(self):
- return len(object.__getattribute__(self, '_get_target')())
-
- def __repr__(self):
- return repr(object.__getattribute__(self, '_get_target')())
-
- def __str__(self):
- return str(object.__getattribute__(self, '_get_target')())
-
- def __hash__(self):
- return hash(object.__getattribute__(self, '_get_target')())
-
- def __eq__(self, other):
- return object.__getattribute__(self, '_get_target')() == other
-
- def __ne__(self, other):
- return object.__getattribute__(self, '_get_target')() != other
-
- def __nonzero__(self):
- return bool(object.__getattribute__(self, '_get_target')())
-
-class _LazyImport(ObjectProxy):
-
- __slots__ = ('_scope', '_alias', '_name', '_target')
-
- def __init__(self, scope, alias, name):
- ObjectProxy.__init__(self)
- object.__setattr__(self, '_scope', scope)
- object.__setattr__(self, '_alias', alias)
- object.__setattr__(self, '_name', name)
-
- def _get_target(self):
- try:
- return object.__getattribute__(self, '_target')
- except AttributeError:
- pass
- name = object.__getattribute__(self, '_name')
- __import__(name)
- target = sys.modules[name]
- object.__setattr__(self, '_target', target)
- object.__getattribute__(self, '_scope')[
- object.__getattribute__(self, '_alias')] = target
- return target
-
-class _LazyImportFrom(_LazyImport):
-
- __slots__ = ()
-
- def _get_target(self):
- try:
- return object.__getattribute__(self, '_target')
- except AttributeError:
- pass
- name = object.__getattribute__(self, '_name')
- components = name.split('.')
- parent_name = '.'.join(components[:-1])
- __import__(parent_name)
- target = getattr(sys.modules[parent_name], components[-1])
- object.__setattr__(self, '_target', target)
- object.__getattribute__(self, '_scope')[
- object.__getattribute__(self, '_alias')] = target
- return target
-
-def lazy_import(scope, *args):
- """
- Create a proxy in the given scope in order to performa a lazy import.
-
- Syntax Result
- foo import foo
- foo:bar,baz from foo import bar, baz
- foo:bar@baz from foo import bar as baz
-
- @param scope: the scope in which to place the import, typically globals()
- @type myfilename: dict
- @param args: module names to import
- @type args: strings
- """
-
- for s in args:
- parts = s.split(':', 1)
- if len(parts) == 1:
- name = s
-
- if not name or not isinstance(name, basestring):
- raise ValueError(name)
-
- components = name.split('.')
- parent_scope = scope
- for i in xrange(len(components)):
- alias = components[i]
- mod = parent_scope.get(alias)
- if isinstance(mod, types.ModuleType):
- parent_scope = mod.__dict__
- continue
- if i < len(components) - 1:
- parent_name = ".".join(components[:i+1])
- __import__(parent_name)
- mod = sys.modules.get(parent_name)
- if not isinstance(mod, types.ModuleType):
- # raise an exception
- __import__(name)
- parent_scope[alias] = mod
- parent_scope = mod.__dict__
- continue
- parent_scope[alias] = _LazyImport(parent_scope, alias, name)
-
- else:
- name, fromlist = parts
- fromlist = fromlist.split(',')
- for s in fromlist:
- alias = s.split('@', 1)
- if len(alias) == 1:
- alias = alias[0]
- orig = alias
- else:
- orig, alias = alias
- scope[alias] = _LazyImportFrom(scope, alias,
- name + '.' + orig)
-
class _tolerant_shlex(shlex.shlex):
def sourcehook(self, newfile):
try:
"""A mapping object that behaves like a standard dict except that it allows
for lazy initialization of values via callable objects. Lazy items can be
overwritten and deleted just as normal items."""
- def __init__(self, initial_items=None):
+
+ __slots__ = ('lazy_items',)
+
+ def __init__(self, *args, **kwargs):
+
+ if len(args) > 1:
+ raise TypeError(
+ "expected at most 1 positional argument, got " + \
+ repr(len(args)))
+
dict.__init__(self)
self.lazy_items = {}
- if initial_items is not None:
- self.update(initial_items)
+
+ if args:
+ self.update(args[0])
+
+ if kwargs:
+ self.update(kwargs)
+
def addLazyItem(self, item_key, value_callable, *pargs, **kwargs):
"""Add a lazy item for the given key. When the item is requested,
value_callable will be called with *pargs and **kwargs arguments."""
def addLazySingleton(self, item_key, value_callable, *pargs, **kwargs):
"""This is like addLazyItem except value_callable will only be called
a maximum of 1 time and the result will be cached for future requests."""
- class SingletonItem(object):
- def __init__(self, value_callable, *pargs, **kwargs):
- self._callable = value_callable
- self._pargs = pargs
- self._kwargs = kwargs
- self._called = False
- def __call__(self):
- if not self._called:
- self._called = True
- self._value = self._callable(*self._pargs, **self._kwargs)
- return self._value
- self.addLazyItem(item_key, SingletonItem(value_callable, *pargs, **kwargs))
+ self.addLazyItem(item_key,
+ self._SingletonWrapper(self, item_key, value_callable,
+ *pargs, **kwargs))
def update(self, map_obj):
if isinstance(map_obj, LazyItemsDict):
for k in map_obj:
del self.lazy_items[item_key]
dict.__delitem__(self, item_key)
+ def clear(self):
+ self.lazy_items.clear()
+ dict.clear(self)
+
+ def copy(self):
+ return self.__copy__()
+
+ def __copy__(self):
+ return self.__class__(self)
+
+ def __deepcopy__(self, memo=None):
+ """
+ WARNING: If any of the lazy items contains a bound method then it's
+ typical for deepcopy() to raise an exception like this:
+
+ File "/usr/lib/python2.5/copy.py", line 189, in deepcopy
+ y = _reconstruct(x, rv, 1, memo)
+ File "/usr/lib/python2.5/copy.py", line 322, in _reconstruct
+ y = callable(*args)
+ File "/usr/lib/python2.5/copy_reg.py", line 92, in __newobj__
+ return cls.__new__(cls, *args)
+ TypeError: instancemethod expected at least 2 arguments, got 0
+
+ If deepcopy() needs to work, this problem can be avoided by
+ implementing lazy items with normal (non-bound) functions.
+ """
+ if memo is None:
+ memo = {}
+ from copy import deepcopy
+ result = self.__class__()
+ memo[id(self)] = result
+ for k in self:
+ k_copy = deepcopy(k, memo)
+ if k in self.lazy_items:
+ dict.__setitem__(result, k_copy, None)
+ result.lazy_items[k_copy] = \
+ deepcopy(self.lazy_items[k], memo)
+ else:
+ dict.__setitem__(result, k_copy, deepcopy(self[k], memo))
+ return result
+
+ class _SingletonWrapper(object):
+
+ __slots__ = ('_parent', '_key', '_callable', '_pargs', '_kwargs')
+
+ def __init__(self, parent, key, value_callable, *pargs, **kwargs):
+ self._parent = parent
+ self._key = key
+ self._callable = value_callable
+ self._pargs = pargs
+ self._kwargs = kwargs
+
+ def __call__(self):
+ value = self._callable(*self._pargs, **self._kwargs)
+ self._parent[self._key] = value
+ return value
+
class ConfigProtect(object):
def __init__(self, myroot, protect_list, mask_list):
self.myroot = myroot