/Demo/imputil/knee.py
Python | 126 lines | 123 code | 0 blank | 3 comment | 0 complexity | ef683a99aa1cd68d9f8297eb44584a52 MD5 | raw file
1"""An Python re-implementation of hierarchical module import. 2 3This code is intended to be read, not executed. However, it does work 4-- all you need to do to enable it is "import knee". 5 6(The name is a pun on the klunkier predecessor of this module, "ni".) 7 8""" 9 10import sys, imp, __builtin__ 11 12 13# Replacement for __import__() 14def import_hook(name, globals=None, locals=None, fromlist=None): 15 parent = determine_parent(globals) 16 q, tail = find_head_package(parent, name) 17 m = load_tail(q, tail) 18 if not fromlist: 19 return q 20 if hasattr(m, "__path__"): 21 ensure_fromlist(m, fromlist) 22 return m 23 24def determine_parent(globals): 25 if not globals or not globals.has_key("__name__"): 26 return None 27 pname = globals['__name__'] 28 if globals.has_key("__path__"): 29 parent = sys.modules[pname] 30 assert globals is parent.__dict__ 31 return parent 32 if '.' in pname: 33 i = pname.rfind('.') 34 pname = pname[:i] 35 parent = sys.modules[pname] 36 assert parent.__name__ == pname 37 return parent 38 return None 39 40def find_head_package(parent, name): 41 if '.' in name: 42 i = name.find('.') 43 head = name[:i] 44 tail = name[i+1:] 45 else: 46 head = name 47 tail = "" 48 if parent: 49 qname = "%s.%s" % (parent.__name__, head) 50 else: 51 qname = head 52 q = import_module(head, qname, parent) 53 if q: return q, tail 54 if parent: 55 qname = head 56 parent = None 57 q = import_module(head, qname, parent) 58 if q: return q, tail 59 raise ImportError, "No module named " + qname 60 61def load_tail(q, tail): 62 m = q 63 while tail: 64 i = tail.find('.') 65 if i < 0: i = len(tail) 66 head, tail = tail[:i], tail[i+1:] 67 mname = "%s.%s" % (m.__name__, head) 68 m = import_module(head, mname, m) 69 if not m: 70 raise ImportError, "No module named " + mname 71 return m 72 73def ensure_fromlist(m, fromlist, recursive=0): 74 for sub in fromlist: 75 if sub == "*": 76 if not recursive: 77 try: 78 all = m.__all__ 79 except AttributeError: 80 pass 81 else: 82 ensure_fromlist(m, all, 1) 83 continue 84 if sub != "*" and not hasattr(m, sub): 85 subname = "%s.%s" % (m.__name__, sub) 86 submod = import_module(sub, subname, m) 87 if not submod: 88 raise ImportError, "No module named " + subname 89 90def import_module(partname, fqname, parent): 91 try: 92 return sys.modules[fqname] 93 except KeyError: 94 pass 95 try: 96 fp, pathname, stuff = imp.find_module(partname, 97 parent and parent.__path__) 98 except ImportError: 99 return None 100 try: 101 m = imp.load_module(fqname, fp, pathname, stuff) 102 finally: 103 if fp: fp.close() 104 if parent: 105 setattr(parent, partname, m) 106 return m 107 108 109# Replacement for reload() 110def reload_hook(module): 111 name = module.__name__ 112 if '.' not in name: 113 return import_module(name, name, None) 114 i = name.rfind('.') 115 pname = name[:i] 116 parent = sys.modules[pname] 117 return import_module(name[i+1:], name, parent) 118 119 120# Save the original hooks 121original_import = __builtin__.__import__ 122original_reload = __builtin__.reload 123 124# Now install our hooks 125__builtin__.__import__ = import_hook 126__builtin__.reload = reload_hook