# 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

if sys.hexversion >= 0x3000000:
	basestring = str

_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.items()):
				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 range(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)
