From b111f7defd5e1cbc704d7a4cf500a139807b8b1f Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Sun, 22 Feb 2009 02:46:26 +0000 Subject: Reduce bloat in portage.util by splitting ObjectProxy and lazyimport into a new portage.proxy package. svn path=/main/trunk/; revision=12676 --- pym/portage/proxy/__init__.py | 3 + pym/portage/proxy/lazyimport.py | 118 +++++++++++++++++++++++++++++++++++++++ pym/portage/proxy/objectproxy.py | 66 ++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 pym/portage/proxy/__init__.py create mode 100644 pym/portage/proxy/lazyimport.py create mode 100644 pym/portage/proxy/objectproxy.py (limited to 'pym/portage/proxy') diff --git a/pym/portage/proxy/__init__.py b/pym/portage/proxy/__init__.py new file mode 100644 index 000000000..95cbda1ed --- /dev/null +++ b/pym/portage/proxy/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ diff --git a/pym/portage/proxy/lazyimport.py b/pym/portage/proxy/lazyimport.py new file mode 100644 index 000000000..6e9717642 --- /dev/null +++ b/pym/portage/proxy/lazyimport.py @@ -0,0 +1,118 @@ +# Copyright 2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +__all__ = ['lazy_import'] + +import sys +import types +from portage.proxy.objectproxy import ObjectProxy + +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 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] + orig = alias + else: + orig, alias = alias + if already_imported is not None: + try: + scope[alias] = getattr(already_imported, orig) + except AttributeError: + raise ImportError('cannot import name %s' % orig) + else: + scope[alias] = _LazyImportFrom(scope, alias, + name + '.' + orig) diff --git a/pym/portage/proxy/objectproxy.py b/pym/portage/proxy/objectproxy.py new file mode 100644 index 000000000..00d3f6157 --- /dev/null +++ b/pym/portage/proxy/objectproxy.py @@ -0,0 +1,66 @@ +# 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')()) -- cgit v1.2.3-1-g7c22