Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/demandimport.py @ 3886:abaee83ce0a6
Replace demandload with new demandimport
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 13 Dec 2006 13:27:09 -0600 |
parents | |
children | 3b628b5da9e9 f47afa2401a2 |
comparison
equal
deleted
inserted
replaced
3885:1e0b94cfba0e | 3886:abaee83ce0a6 |
---|---|
1 # demandimport.py - global demand-loading of modules for Mercurial | |
2 # | |
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
8 ''' | |
9 demandimport - automatic demandloading of modules | |
10 | |
11 To enable this module, do: | |
12 | |
13 import demandimport; demandimport.enable() | |
14 | |
15 Imports of the following forms will be demand-loaded: | |
16 | |
17 import a, b.c | |
18 import a.b as c | |
19 from a import b,c # a will be loaded immediately | |
20 | |
21 These imports will not be delayed: | |
22 | |
23 from a import * | |
24 b = __import__(a) | |
25 ''' | |
26 | |
27 _origimport = __import__ | |
28 | |
29 class _demandmod(object): | |
30 """module demand-loader and proxy""" | |
31 def __init__(self, name, globals, locals): | |
32 if '.' in name: | |
33 head, rest = name.split('.', 1) | |
34 after = [rest] | |
35 else: | |
36 head = name | |
37 after = [] | |
38 self.__dict__["_data"] = (head, globals, locals, after) | |
39 self.__dict__["_module"] = None | |
40 def _extend(self, name): | |
41 """add to the list of submodules to load""" | |
42 self._data[3].append(name) | |
43 def _load(self): | |
44 if not self._module: | |
45 head, globals, locals, after = self._data | |
46 mod = _origimport(head, globals, locals) | |
47 # load submodules | |
48 for x in after: | |
49 hx = x | |
50 if '.' in x: | |
51 hx = x.split('.')[0] | |
52 if not hasattr(mod, hx): | |
53 setattr(mod, hx, _demandmod(x, mod.__dict__, mod.__dict__)) | |
54 # are we in the locals dictionary still? | |
55 if locals and locals.get(head) == self: | |
56 locals[head] = mod | |
57 self.__dict__["_module"] = mod | |
58 def __repr__(self): | |
59 return "<unloaded module '%s'>" % self._data[0] | |
60 def __call__(self, *args, **kwargs): | |
61 raise TypeError("'unloaded module' object is not callable") | |
62 def __getattr__(self, attr): | |
63 self._load() | |
64 return getattr(self._module, attr) | |
65 def __setattr__(self, attr, val): | |
66 self._load() | |
67 setattr(self._module, attr, val) | |
68 | |
69 def _demandimport(name, globals=None, locals=None, fromlist=None): | |
70 if not locals or name in ignore or fromlist == ('*',): | |
71 # these cases we can't really delay | |
72 return _origimport(name, globals, locals, fromlist) | |
73 elif not fromlist: | |
74 # import a [as b] | |
75 if '.' in name: # a.b | |
76 base, rest = name.split('.', 1) | |
77 # if a is already demand-loaded, add b to its submodule list | |
78 if base in locals: | |
79 if isinstance(locals[base], _demandmod): | |
80 locals[base]._extend(rest) | |
81 return locals[base] | |
82 return _demandmod(name, globals, locals) | |
83 else: | |
84 # from a import b,c,d | |
85 mod = _origimport(name, globals, locals) | |
86 # recurse down the module chain | |
87 for comp in name.split('.')[1:]: | |
88 mod = getattr(mod, comp) | |
89 for x in fromlist: | |
90 # set requested submodules for demand load | |
91 if not(hasattr(mod, x)): | |
92 setattr(mod, x, _demandmod(x, mod.__dict__, mod.__dict__)) | |
93 return mod | |
94 | |
95 ignore = [] | |
96 | |
97 def enable(): | |
98 "enable global demand-loading of modules" | |
99 __builtins__["__import__"] = _demandimport | |
100 | |
101 def disable(): | |
102 "disable global demand-loading of modules" | |
103 __builtins__["__import__"] = _origimport | |
104 |