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