From: Zac Medico Date: Fri, 20 Feb 2009 06:15:34 +0000 (-0000) Subject: Add a new portage.utils.lazy_import() function which behaves similar to the X-Git-Tag: v2.2_rc24~150 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=fb05e64acc278e4395b4209e2219c404b3697252;p=portage.git Add a new portage.utils.lazy_import() function which behaves similar to the snakeoil.demandload.demandload() function. svn path=/main/trunk/; revision=12661 --- diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py index 15af77571..621daa7be 100644 --- a/pym/portage/__init__.py +++ b/pym/portage/__init__.py @@ -73,17 +73,30 @@ if platform.system() in ["FreeBSD"]: try: from portage.cache.cache_errors import CacheError - import portage.cvstree - import portage.xpak - import portage.getbinpkg - import portage.dep - from portage.dep import dep_getcpv, dep_getkey, get_operator, \ - isjustname, isspecific, isvalidatom, \ - match_from_list, match_to_list, best_match_to_list - - # XXX: This needs to get cleaned up. - import portage.output - from portage.output import bold, colorize, green, red, yellow + import portage.util as util + util.lazy_import(globals(), + 'portage.checksum', + 'portage.checksum:perform_checksum,perform_md5,prelink_capable', + 'portage.cvstree', + 'portage.dep', + 'portage.dep:best_match_to_list,dep_getcpv,dep_getkey,' + \ + 'get_operator,isjustname,isspecific,isvalidatom,' + \ + 'match_from_list,match_to_list', + 'portage.eclass_cache', + 'portage.getbinpkg', + 'portage.locks', + 'portage.locks:lockdir,lockfile,unlockdir,unlockfile', + 'portage.output', + 'portage.output:bold,colorize', + 'portage.process', + 'portage.process:atexit_register,run_exitfuncs', + 'portage.update:dep_transform,fixdbentries,grab_updates,' + \ + 'parse_updates,update_config_files,update_dbentries,' + \ + 'update_dbentry', + 'portage.versions:best,catpkgsplit,catsplit,endversion_keys,' + \ + 'suffix_value@endversion,pkgcmp,pkgsplit,vercmp,ververify', + 'portage.xpak', + ) import portage.const from portage.const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \ @@ -99,31 +112,13 @@ try: portage_uid, portage_gid, userpriv_groups from portage.manifest import Manifest - import portage.util 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 - import portage.locks - import portage.process - from portage.process import atexit_register, run_exitfuncs - from portage.locks import unlockfile,unlockdir,lockfile,lockdir - import portage.checksum - from portage.checksum import perform_md5,perform_checksum,prelink_capable - import portage.eclass_cache from portage.localization import _ - from portage.update import dep_transform, fixdbentries, grab_updates, \ - parse_updates, update_config_files, update_dbentries, update_dbentry - - # Need these functions directly in portage namespace to not break every external tool in existence - from portage.versions import best, catpkgsplit, catsplit, pkgcmp, \ - pkgsplit, vercmp, ververify - - # endversion and endversion_keys are for backward compatibility only. - from portage.versions import endversion_keys - from portage.versions import suffix_value as endversion except ImportError, e: sys.stderr.write("\n\n") diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py index 7f2c0cbf0..1d2c17ab8 100644 --- a/pym/portage/dbapi/bintree.py +++ b/pym/portage/dbapi/bintree.py @@ -16,7 +16,7 @@ from portage.update import update_dbentries from portage import dep_expand, listdir, _check_distfile, _movefile -import portage.xpak, portage.getbinpkg +import portage import os, errno, stat import re diff --git a/pym/portage/util.py b/pym/portage/util.py index da79d86fe..54df38192 100644 --- a/pym/portage/util.py +++ b/pym/portage/util.py @@ -10,6 +10,7 @@ import shlex import stat import string import sys +import types from portage.exception import PortageException, FileNotFound, \ OperationNotPermitted, PermissionDenied, ReadOnlyFileSystem @@ -341,6 +342,8 @@ class ObjectProxy(object): for implementing lazy initialization. """ + __slots__ = () + def _get_target(self): raise NotImplementedError(self) @@ -392,6 +395,104 @@ class ObjectProxy(object): 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: