mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""An Python re-implementation of hierarchical module import.
 | 
						|
 | 
						|
This code is intended to be read, not executed.  However, it does work
 | 
						|
-- all you need to do to enable it is "import knee".
 | 
						|
 | 
						|
(The name is a pun on the klunkier predecessor of this module, "ni".)
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import sys, imp, __builtin__, string
 | 
						|
 | 
						|
 | 
						|
# Replacement for __import__()
 | 
						|
def import_hook(name, globals=None, locals=None, fromlist=None):
 | 
						|
    parent = determine_parent(globals)
 | 
						|
    q, tail = find_head_package(parent, name)
 | 
						|
    m = load_tail(q, tail)
 | 
						|
    if not fromlist:
 | 
						|
        return q
 | 
						|
    if hasattr(m, "__path__"):
 | 
						|
        ensure_fromlist(m, fromlist)
 | 
						|
    return m
 | 
						|
 | 
						|
def determine_parent(globals):
 | 
						|
    if not globals or  not globals.has_key("__name__"):
 | 
						|
        return None
 | 
						|
    pname = globals['__name__']
 | 
						|
    if globals.has_key("__path__"):
 | 
						|
        parent = sys.modules[pname]
 | 
						|
        assert globals is parent.__dict__
 | 
						|
        return parent
 | 
						|
    if '.' in pname:
 | 
						|
        i = string.rfind(pname, '.')
 | 
						|
        pname = pname[:i]
 | 
						|
        parent = sys.modules[pname]
 | 
						|
        assert parent.__name__ == pname
 | 
						|
        return parent
 | 
						|
    return None
 | 
						|
 | 
						|
def find_head_package(parent, name):
 | 
						|
    if '.' in name:
 | 
						|
        i = string.find(name, '.')
 | 
						|
        head = name[:i]
 | 
						|
        tail = name[i+1:]
 | 
						|
    else:
 | 
						|
        head = name
 | 
						|
        tail = ""
 | 
						|
    if parent:
 | 
						|
        qname = "%s.%s" % (parent.__name__, head)
 | 
						|
    else:
 | 
						|
        qname = head
 | 
						|
    q = import_module(head, qname, parent)
 | 
						|
    if q: return q, tail
 | 
						|
    if parent:
 | 
						|
        qname = head
 | 
						|
        parent = None
 | 
						|
        q = import_module(head, qname, parent)
 | 
						|
        if q: return q, tail
 | 
						|
    raise ImportError, "No module named " + qname
 | 
						|
 | 
						|
def load_tail(q, tail):
 | 
						|
    m = q
 | 
						|
    while tail:
 | 
						|
        i = string.find(tail, '.')
 | 
						|
        if i < 0: i = len(tail)
 | 
						|
        head, tail = tail[:i], tail[i+1:]
 | 
						|
        mname = "%s.%s" % (m.__name__, head)
 | 
						|
        m = import_module(head, mname, m)
 | 
						|
        if not m:
 | 
						|
            raise ImportError, "No module named " + mname
 | 
						|
    return m
 | 
						|
 | 
						|
def ensure_fromlist(m, fromlist, recursive=0):
 | 
						|
    for sub in fromlist:
 | 
						|
        if sub == "*":
 | 
						|
            if not recursive:
 | 
						|
                try:
 | 
						|
                    all = m.__all__
 | 
						|
                except AttributeError:
 | 
						|
                    pass
 | 
						|
                else:
 | 
						|
                    ensure_fromlist(m, all, 1)
 | 
						|
            continue
 | 
						|
        if sub != "*" and not hasattr(m, sub):
 | 
						|
            subname = "%s.%s" % (m.__name__, sub)
 | 
						|
            submod = import_module(sub, subname, m)
 | 
						|
            if not submod:
 | 
						|
                raise ImportError, "No module named " + subname
 | 
						|
 | 
						|
def import_module(partname, fqname, parent):
 | 
						|
    try:
 | 
						|
        return sys.modules[fqname]
 | 
						|
    except KeyError:
 | 
						|
        pass
 | 
						|
    try:
 | 
						|
        fp, pathname, stuff = imp.find_module(partname,
 | 
						|
                                              parent and parent.__path__)
 | 
						|
    except ImportError:
 | 
						|
        return None
 | 
						|
    try:
 | 
						|
        m = imp.load_module(fqname, fp, pathname, stuff)
 | 
						|
    finally:
 | 
						|
        if fp: fp.close()
 | 
						|
    if parent:
 | 
						|
        setattr(parent, partname, m)
 | 
						|
    return m
 | 
						|
 | 
						|
 | 
						|
# Replacement for reload()
 | 
						|
def reload_hook(module):
 | 
						|
    name = module.__name__
 | 
						|
    if '.' not in name:
 | 
						|
        return import_module(name, name, None)
 | 
						|
    i = string.rfind(name, '.')
 | 
						|
    pname = name[:i]
 | 
						|
    parent = sys.modules[pname]
 | 
						|
    return import_module(name[i+1:], name, parent)
 | 
						|
 | 
						|
 | 
						|
# Save the original hooks
 | 
						|
original_import = __builtin__.__import__
 | 
						|
original_reload = __builtin__.reload
 | 
						|
 | 
						|
# Now install our hooks
 | 
						|
__builtin__.__import__ = import_hook
 | 
						|
__builtin__.reload = reload_hook
 |