##// END OF EJS Templates
Keep original function names.
Bradley M. Froehle -
Show More
@@ -1,320 +1,320 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 A module to change reload() so that it acts recursively.
4 4 To enable it type::
5 5
6 6 import __builtin__, deepreload
7 7 __builtin__.reload = deepreload.reload
8 8
9 9 You can then disable it with::
10 10
11 11 __builtin__.reload = deepreload.original_reload
12 12
13 13 Alternatively, you can add a dreload builtin alongside normal reload with::
14 14
15 15 __builtin__.dreload = deepreload.reload
16 16
17 17 This code is almost entirely based on knee.py, which is a Python
18 18 re-implementation of hierarchical module import.
19 19 """
20 20 #*****************************************************************************
21 21 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
22 22 #
23 23 # Distributed under the terms of the BSD License. The full license is in
24 24 # the file COPYING, distributed as part of this software.
25 25 #*****************************************************************************
26 26
27 27 import __builtin__
28 28 import imp
29 29 import sys
30 30
31 31 from types import ModuleType
32 32 from warnings import warn
33 33
34 34 def get_parent(globals, level):
35 35 """
36 36 parent, name = get_parent(globals, level)
37 37
38 38 Return the package that an import is being performed in. If globals comes
39 39 from the module foo.bar.bat (not itself a package), this returns the
40 40 sys.modules entry for foo.bar. If globals is from a package's __init__.py,
41 41 the package's entry in sys.modules is returned.
42 42
43 43 If globals doesn't come from a package or a module in a package, or a
44 44 corresponding entry is not found in sys.modules, None is returned.
45 45 """
46 46 orig_level = level
47 47
48 48 if not level or not isinstance(globals, dict):
49 49 return None, ''
50 50
51 51 pkgname = globals.get('__package__', None)
52 52
53 53 if pkgname is not None:
54 54 # __package__ is set, so use it
55 55 if not hasattr(pkgname, 'rindex'):
56 56 raise ValueError('__package__ set to non-string')
57 57 if len(pkgname) == 0:
58 58 if level > 0:
59 59 raise ValueError('Attempted relative import in non-package')
60 60 return None, ''
61 61 name = pkgname
62 62 else:
63 63 # __package__ not set, so figure it out and set it
64 64 if '__name__' not in globals:
65 65 return None, ''
66 66 modname = globals['__name__']
67 67
68 68 if '__path__' in globals:
69 69 # __path__ is set, so modname is already the package name
70 70 globals['__package__'] = name = modname
71 71 else:
72 72 # Normal module, so work out the package name if any
73 73 lastdot = modname.rfind('.')
74 74 if lastdot < 0 and level > 0:
75 75 raise ValueError("Attempted relative import in non-package")
76 76 if lastdot < 0:
77 77 globals['__package__'] = None
78 78 return None, ''
79 79 globals['__package__'] = name = modname[:lastdot]
80 80
81 81 dot = len(name)
82 82 for x in xrange(level, 1, -1):
83 83 try:
84 84 dot = name.rindex('.', 0, dot)
85 85 except ValueError:
86 86 raise ValueError("attempted relative import beyond top-level "
87 87 "package")
88 88 name = name[:dot]
89 89
90 90 try:
91 91 parent = sys.modules[name]
92 92 except:
93 93 if orig_level < 1:
94 94 warn("Parent module '%.200s' not found while handling absolute "
95 95 "import" % name)
96 96 parent = None
97 97 else:
98 98 raise SystemError("Parent module '%.200s' not loaded, cannot "
99 99 "perform relative import" % name)
100 100
101 101 # We expect, but can't guarantee, if parent != None, that:
102 102 # - parent.__name__ == name
103 103 # - parent.__dict__ is globals
104 104 # If this is violated... Who cares?
105 105 return parent, name
106 106
107 107 def load_next(mod, altmod, name, buf):
108 108 """
109 109 mod, name, buf = load_next(mod, altmod, name, buf)
110 110
111 111 altmod is either None or same as mod
112 112 """
113 113
114 114 if len(name) == 0:
115 115 # completely empty module name should only happen in
116 116 # 'from . import' (or '__import__("")')
117 117 return mod, None, buf
118 118
119 119 dot = name.find('.')
120 120 if dot == 0:
121 121 raise ValueError('Empty module name')
122 122
123 123 if dot < 0:
124 124 subname = name
125 125 next = None
126 126 else:
127 127 subname = name[:dot]
128 128 next = name[dot+1:]
129 129
130 130 if buf != '':
131 131 buf += '.'
132 132 buf += subname
133 133
134 134 result = import_submodule(mod, subname, buf)
135 135 if result is None and mod != altmod:
136 136 result = import_submodule(altmod, subname, subname)
137 137 if result is not None:
138 138 buf = subname
139 139
140 140 if result is None:
141 141 raise ImportError("No module named %.200s" % name)
142 142
143 143 return result, next, buf
144 144
145 145 # Need to keep track of what we've already reloaded to prevent cyclic evil
146 146 found_now = {}
147 147
148 148 def import_submodule(mod, subname, fullname):
149 149 """m = import_submodule(mod, subname, fullname)"""
150 150 # Require:
151 151 # if mod == None: subname == fullname
152 152 # else: mod.__name__ + "." + subname == fullname
153 153
154 154 global found_now
155 155 if fullname in found_now and fullname in sys.modules:
156 156 m = sys.modules[fullname]
157 157 else:
158 158 print 'Reloading', fullname
159 159 found_now[fullname] = 1
160 160 oldm = sys.modules.get(fullname, None)
161 161
162 162 if mod is None:
163 163 path = None
164 164 elif hasattr(mod, '__path__'):
165 165 path = mod.__path__
166 166 else:
167 167 return None
168 168
169 169 try:
170 170 fp, filename, stuff = imp.find_module(subname, path)
171 171 except ImportError:
172 172 return None
173 173
174 174 try:
175 175 m = imp.load_module(fullname, fp, filename, stuff)
176 176 except:
177 177 # load_module probably removed name from modules because of
178 178 # the error. Put back the original module object.
179 179 if oldm:
180 180 sys.modules[fullname] = oldm
181 181 raise
182 182 finally:
183 183 if fp: fp.close()
184 184
185 185 add_submodule(mod, m, fullname, subname)
186 186
187 187 return m
188 188
189 189 def add_submodule(mod, submod, fullname, subname):
190 190 """mod.{subname} = submod"""
191 191 if mod is None:
192 192 return #Nothing to do here.
193 193
194 194 if submod is None:
195 195 submod = sys.modules[fullname]
196 196
197 197 setattr(mod, subname, submod)
198 198
199 199 return
200 200
201 201 def ensure_fromlist(mod, fromlist, buf, recursive):
202 202 """Handle 'from module import a, b, c' imports."""
203 203 if not hasattr(mod, '__path__'):
204 204 return
205 205 for item in fromlist:
206 206 if not hasattr(item, 'rindex'):
207 207 raise TypeError("Item in ``from list'' not a string")
208 208 if item == '*':
209 209 if recursive:
210 210 continue # avoid endless recursion
211 211 try:
212 212 all = mod.__all__
213 213 except AttributeError:
214 214 pass
215 215 else:
216 216 ret = ensure_fromlist(mod, all, buf, 1)
217 217 if not ret:
218 218 return 0
219 219 elif not hasattr(mod, item):
220 220 import_submodule(mod, item, buf + '.' + item)
221 221
222 def import_module_level(name, globals=None, locals=None, fromlist=None, level=-1):
222 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
223 223 """Replacement for __import__()"""
224 224 parent, buf = get_parent(globals, level)
225 225
226 226 head, name, buf = load_next(parent, None if level < 0 else parent, name, buf)
227 227
228 228 tail = head
229 229 while name:
230 230 tail, name, buf = load_next(tail, tail, name, buf)
231 231
232 232 # If tail is None, both get_parent and load_next found
233 233 # an empty module name: someone called __import__("") or
234 234 # doctored faulty bytecode
235 235 if tail is None:
236 236 raise ValueError('Empty module name')
237 237
238 238 if not fromlist:
239 239 return head
240 240
241 241 ensure_fromlist(tail, fromlist, buf, 0)
242 242 return tail
243 243
244 244 modules_reloading = {}
245 245
246 def reload_module(m):
246 def deep_reload_hook(m):
247 247 """Replacement for reload()."""
248 248 if not isinstance(m, ModuleType):
249 249 raise TypeError("reload() argument must be module")
250 250
251 251 name = m.__name__
252 252
253 253 if name not in sys.modules:
254 254 raise ImportError("reload(): module %.200s not in sys.modules" % name)
255 255
256 256 global modules_reloading
257 257 try:
258 258 return modules_reloading[name]
259 259 except:
260 260 modules_reloading[name] = m
261 261
262 262 dot = name.rfind('.')
263 263 if dot < 0:
264 264 subname = name
265 265 path = None
266 266 else:
267 267 try:
268 268 parent = sys.modules[name[:dot]]
269 269 except KeyError:
270 270 modules_reloading.clear()
271 271 raise ImportError("reload(): parent %.200s not in sys.modules" % name[:dot])
272 272 subname = name[dot+1:]
273 273 path = getattr(parent, "__path__", None)
274 274
275 275 try:
276 276 fp, filename, stuff = imp.find_module(subname, path)
277 277 finally:
278 278 modules_reloading.clear()
279 279
280 280 try:
281 281 newm = imp.load_module(name, fp, filename, stuff)
282 282 except:
283 283 # load_module probably removed name from modules because of
284 284 # the error. Put back the original module object.
285 285 sys.modules[name] = m
286 286 raise
287 287 finally:
288 288 if fp: fp.close()
289 289
290 290 modules_reloading.clear()
291 291 return newm
292 292
293 293 # Save the original hooks
294 294 try:
295 295 original_reload = __builtin__.reload
296 296 except AttributeError:
297 297 original_reload = imp.reload # Python 3
298 298
299 299 # Replacement for reload()
300 300 def reload(module, exclude=['sys', 'os.path', '__builtin__', '__main__']):
301 301 """Recursively reload all modules used in the given module. Optionally
302 302 takes a list of modules to exclude from reloading. The default exclude
303 303 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
304 304 display, exception, and io hooks.
305 305 """
306 306 global found_now
307 307 for i in exclude:
308 308 found_now[i] = 1
309 309 original_import = __builtin__.__import__
310 __builtin__.__import__ = import_module_level
310 __builtin__.__import__ = deep_import_hook
311 311 try:
312 ret = reload_module(module)
312 ret = deep_reload_hook(module)
313 313 finally:
314 314 __builtin__.__import__ = original_import
315 315 found_now = {}
316 316 return ret
317 317
318 318 # Uncomment the following to automatically activate deep reloading whenever
319 319 # this module is imported
320 320 #__builtin__.reload = reload
General Comments 0
You need to be logged in to leave comments. Login now