blob: 95c3c231649371a57f2e0f6e6f3bedb3b1aba252 [file] [log] [blame]
Guido van Rossum4ece95d1997-09-09 20:44:04 +00001"""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"""
Guido van Rossum501d0bb1997-09-09 20:35:20 +00009
10import sys, imp, __builtin__, string
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:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000019 return q
Guido van Rossum501d0bb1997-09-09 20:35:20 +000020 if hasattr(m, "__path__"):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000021 ensure_fromlist(m, fromlist)
Guido van Rossum501d0bb1997-09-09 20:35:20 +000022 return m
23
24def determine_parent(globals):
25 if not globals or not globals.has_key("__name__"):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000026 return None
Guido van Rossum501d0bb1997-09-09 20:35:20 +000027 pname = globals['__name__']
28 if globals.has_key("__path__"):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000029 parent = sys.modules[pname]
30 assert globals is parent.__dict__
31 return parent
Guido van Rossum501d0bb1997-09-09 20:35:20 +000032 if '.' in pname:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000033 i = string.rfind(pname, '.')
34 pname = pname[:i]
35 parent = sys.modules[pname]
36 assert parent.__name__ == pname
37 return parent
Guido van Rossum501d0bb1997-09-09 20:35:20 +000038 return None
39
40def find_head_package(parent, name):
41 if '.' in name:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000042 i = string.find(name, '.')
43 head = name[:i]
44 tail = name[i+1:]
Guido van Rossum501d0bb1997-09-09 20:35:20 +000045 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000046 head = name
47 tail = ""
Guido van Rossum501d0bb1997-09-09 20:35:20 +000048 if parent:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000049 qname = "%s.%s" % (parent.__name__, head)
Guido van Rossum501d0bb1997-09-09 20:35:20 +000050 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000051 qname = head
Guido van Rossum501d0bb1997-09-09 20:35:20 +000052 q = import_module(head, qname, parent)
53 if q: return q, tail
54 if parent:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000055 qname = head
56 parent = None
57 q = import_module(head, qname, parent)
58 if q: return q, tail
Guido van Rossum501d0bb1997-09-09 20:35:20 +000059 raise ImportError, "No module named " + qname
60
61def load_tail(q, tail):
62 m = q
63 while tail:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000064 i = string.find(tail, '.')
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
Guido van Rossum501d0bb1997-09-09 20:35:20 +000071 return m
72
Guido van Rossum4f9f8e31997-09-09 20:39:58 +000073def ensure_fromlist(m, fromlist, recursive=0):
Guido van Rossum501d0bb1997-09-09 20:35:20 +000074 for sub in fromlist:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000075 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
Guido van Rossum501d0bb1997-09-09 20:35:20 +000089
90def import_module(partname, fqname, parent):
91 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000092 return sys.modules[fqname]
Guido van Rossum501d0bb1997-09-09 20:35:20 +000093 except KeyError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 pass
Guido van Rossum501d0bb1997-09-09 20:35:20 +000095 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000096 fp, pathname, stuff = imp.find_module(partname,
97 parent and parent.__path__)
Guido van Rossum501d0bb1997-09-09 20:35:20 +000098 except ImportError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000099 return None
Guido van Rossum501d0bb1997-09-09 20:35:20 +0000100 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101 m = imp.load_module(fqname, fp, pathname, stuff)
Guido van Rossum501d0bb1997-09-09 20:35:20 +0000102 finally:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 if fp: fp.close()
Guido van Rossum501d0bb1997-09-09 20:35:20 +0000104 if parent:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 setattr(parent, partname, m)
Guido van Rossum501d0bb1997-09-09 20:35:20 +0000106 return m
107
108
109# Replacement for reload()
110def reload_hook(module):
111 name = module.__name__
112 if '.' not in name:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 return import_module(name, name, None)
Guido van Rossum501d0bb1997-09-09 20:35:20 +0000114 i = string.rfind(name, '.')
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