##// END OF EJS Templates
demandimport: blacklist distutils.msvc9compiler (issue4475)...
Augie Fackler -
r23643:2205d00b stable
parent child Browse files
Show More
@@ -1,179 +1,181 b''
1 # demandimport.py - global demand-loading of modules for Mercurial
1 # demandimport.py - global demand-loading of modules for Mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''
8 '''
9 demandimport - automatic demandloading of modules
9 demandimport - automatic demandloading of modules
10
10
11 To enable this module, do:
11 To enable this module, do:
12
12
13 import demandimport; demandimport.enable()
13 import demandimport; demandimport.enable()
14
14
15 Imports of the following forms will be demand-loaded:
15 Imports of the following forms will be demand-loaded:
16
16
17 import a, b.c
17 import a, b.c
18 import a.b as c
18 import a.b as c
19 from a import b,c # a will be loaded immediately
19 from a import b,c # a will be loaded immediately
20
20
21 These imports will not be delayed:
21 These imports will not be delayed:
22
22
23 from a import *
23 from a import *
24 b = __import__(a)
24 b = __import__(a)
25 '''
25 '''
26
26
27 import __builtin__, os, sys
27 import __builtin__, os, sys
28 _origimport = __import__
28 _origimport = __import__
29
29
30 nothing = object()
30 nothing = object()
31
31
32 try:
32 try:
33 # Python 3 doesn't have relative imports nor level -1.
33 # Python 3 doesn't have relative imports nor level -1.
34 level = -1
34 level = -1
35 if sys.version_info[0] >= 3:
35 if sys.version_info[0] >= 3:
36 level = 0
36 level = 0
37 _origimport(__builtin__.__name__, {}, {}, None, level)
37 _origimport(__builtin__.__name__, {}, {}, None, level)
38 except TypeError: # no level argument
38 except TypeError: # no level argument
39 def _import(name, globals, locals, fromlist, level):
39 def _import(name, globals, locals, fromlist, level):
40 "call _origimport with no level argument"
40 "call _origimport with no level argument"
41 return _origimport(name, globals, locals, fromlist)
41 return _origimport(name, globals, locals, fromlist)
42 else:
42 else:
43 _import = _origimport
43 _import = _origimport
44
44
45 def _hgextimport(importfunc, name, globals, *args):
45 def _hgextimport(importfunc, name, globals, *args):
46 try:
46 try:
47 return importfunc(name, globals, *args)
47 return importfunc(name, globals, *args)
48 except ImportError:
48 except ImportError:
49 if not globals:
49 if not globals:
50 raise
50 raise
51 # extensions are loaded with "hgext_" prefix
51 # extensions are loaded with "hgext_" prefix
52 hgextname = 'hgext_%s' % name
52 hgextname = 'hgext_%s' % name
53 nameroot = hgextname.split('.', 1)[0]
53 nameroot = hgextname.split('.', 1)[0]
54 contextroot = globals.get('__name__', '').split('.', 1)[0]
54 contextroot = globals.get('__name__', '').split('.', 1)[0]
55 if nameroot != contextroot:
55 if nameroot != contextroot:
56 raise
56 raise
57 # retry to import with "hgext_" prefix
57 # retry to import with "hgext_" prefix
58 return importfunc(hgextname, globals, *args)
58 return importfunc(hgextname, globals, *args)
59
59
60 class _demandmod(object):
60 class _demandmod(object):
61 """module demand-loader and proxy"""
61 """module demand-loader and proxy"""
62 def __init__(self, name, globals, locals, level=level):
62 def __init__(self, name, globals, locals, level=level):
63 if '.' in name:
63 if '.' in name:
64 head, rest = name.split('.', 1)
64 head, rest = name.split('.', 1)
65 after = [rest]
65 after = [rest]
66 else:
66 else:
67 head = name
67 head = name
68 after = []
68 after = []
69 object.__setattr__(self, "_data",
69 object.__setattr__(self, "_data",
70 (head, globals, locals, after, level))
70 (head, globals, locals, after, level))
71 object.__setattr__(self, "_module", None)
71 object.__setattr__(self, "_module", None)
72 def _extend(self, name):
72 def _extend(self, name):
73 """add to the list of submodules to load"""
73 """add to the list of submodules to load"""
74 self._data[3].append(name)
74 self._data[3].append(name)
75 def _load(self):
75 def _load(self):
76 if not self._module:
76 if not self._module:
77 head, globals, locals, after, level = self._data
77 head, globals, locals, after, level = self._data
78 mod = _hgextimport(_import, head, globals, locals, None, level)
78 mod = _hgextimport(_import, head, globals, locals, None, level)
79 # load submodules
79 # load submodules
80 def subload(mod, p):
80 def subload(mod, p):
81 h, t = p, None
81 h, t = p, None
82 if '.' in p:
82 if '.' in p:
83 h, t = p.split('.', 1)
83 h, t = p.split('.', 1)
84 if getattr(mod, h, nothing) is nothing:
84 if getattr(mod, h, nothing) is nothing:
85 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
85 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__))
86 elif t:
86 elif t:
87 subload(getattr(mod, h), t)
87 subload(getattr(mod, h), t)
88
88
89 for x in after:
89 for x in after:
90 subload(mod, x)
90 subload(mod, x)
91
91
92 # are we in the locals dictionary still?
92 # are we in the locals dictionary still?
93 if locals and locals.get(head) == self:
93 if locals and locals.get(head) == self:
94 locals[head] = mod
94 locals[head] = mod
95 object.__setattr__(self, "_module", mod)
95 object.__setattr__(self, "_module", mod)
96
96
97 def __repr__(self):
97 def __repr__(self):
98 if self._module:
98 if self._module:
99 return "<proxied module '%s'>" % self._data[0]
99 return "<proxied module '%s'>" % self._data[0]
100 return "<unloaded module '%s'>" % self._data[0]
100 return "<unloaded module '%s'>" % self._data[0]
101 def __call__(self, *args, **kwargs):
101 def __call__(self, *args, **kwargs):
102 raise TypeError("%s object is not callable" % repr(self))
102 raise TypeError("%s object is not callable" % repr(self))
103 def __getattribute__(self, attr):
103 def __getattribute__(self, attr):
104 if attr in ('_data', '_extend', '_load', '_module'):
104 if attr in ('_data', '_extend', '_load', '_module'):
105 return object.__getattribute__(self, attr)
105 return object.__getattribute__(self, attr)
106 self._load()
106 self._load()
107 return getattr(self._module, attr)
107 return getattr(self._module, attr)
108 def __setattr__(self, attr, val):
108 def __setattr__(self, attr, val):
109 self._load()
109 self._load()
110 setattr(self._module, attr, val)
110 setattr(self._module, attr, val)
111
111
112 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
112 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
113 if not locals or name in ignore or fromlist == ('*',):
113 if not locals or name in ignore or fromlist == ('*',):
114 # these cases we can't really delay
114 # these cases we can't really delay
115 return _hgextimport(_import, name, globals, locals, fromlist, level)
115 return _hgextimport(_import, name, globals, locals, fromlist, level)
116 elif not fromlist:
116 elif not fromlist:
117 # import a [as b]
117 # import a [as b]
118 if '.' in name: # a.b
118 if '.' in name: # a.b
119 base, rest = name.split('.', 1)
119 base, rest = name.split('.', 1)
120 # email.__init__ loading email.mime
120 # email.__init__ loading email.mime
121 if globals and globals.get('__name__', None) == base:
121 if globals and globals.get('__name__', None) == base:
122 return _import(name, globals, locals, fromlist, level)
122 return _import(name, globals, locals, fromlist, level)
123 # if a is already demand-loaded, add b to its submodule list
123 # if a is already demand-loaded, add b to its submodule list
124 if base in locals:
124 if base in locals:
125 if isinstance(locals[base], _demandmod):
125 if isinstance(locals[base], _demandmod):
126 locals[base]._extend(rest)
126 locals[base]._extend(rest)
127 return locals[base]
127 return locals[base]
128 return _demandmod(name, globals, locals, level)
128 return _demandmod(name, globals, locals, level)
129 else:
129 else:
130 if level != -1:
130 if level != -1:
131 # from . import b,c,d or from .a import b,c,d
131 # from . import b,c,d or from .a import b,c,d
132 return _origimport(name, globals, locals, fromlist, level)
132 return _origimport(name, globals, locals, fromlist, level)
133 # from a import b,c,d
133 # from a import b,c,d
134 mod = _hgextimport(_origimport, name, globals, locals)
134 mod = _hgextimport(_origimport, name, globals, locals)
135 # recurse down the module chain
135 # recurse down the module chain
136 for comp in name.split('.')[1:]:
136 for comp in name.split('.')[1:]:
137 if getattr(mod, comp, nothing) is nothing:
137 if getattr(mod, comp, nothing) is nothing:
138 setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
138 setattr(mod, comp, _demandmod(comp, mod.__dict__, mod.__dict__))
139 mod = getattr(mod, comp)
139 mod = getattr(mod, comp)
140 for x in fromlist:
140 for x in fromlist:
141 # set requested submodules for demand load
141 # set requested submodules for demand load
142 if getattr(mod, x, nothing) is nothing:
142 if getattr(mod, x, nothing) is nothing:
143 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
143 setattr(mod, x, _demandmod(x, mod.__dict__, locals))
144 return mod
144 return mod
145
145
146 ignore = [
146 ignore = [
147 '_hashlib',
147 '_hashlib',
148 '_xmlplus',
148 '_xmlplus',
149 'fcntl',
149 'fcntl',
150 'win32com.gen_py',
150 'win32com.gen_py',
151 '_winreg', # 2.7 mimetypes needs immediate ImportError
151 '_winreg', # 2.7 mimetypes needs immediate ImportError
152 'pythoncom',
152 'pythoncom',
153 # imported by tarfile, not available under Windows
153 # imported by tarfile, not available under Windows
154 'pwd',
154 'pwd',
155 'grp',
155 'grp',
156 # imported by profile, itself imported by hotshot.stats,
156 # imported by profile, itself imported by hotshot.stats,
157 # not available under Windows
157 # not available under Windows
158 'resource',
158 'resource',
159 # this trips up many extension authors
159 # this trips up many extension authors
160 'gtk',
160 'gtk',
161 # setuptools' pkg_resources.py expects "from __main__ import x" to
161 # setuptools' pkg_resources.py expects "from __main__ import x" to
162 # raise ImportError if x not defined
162 # raise ImportError if x not defined
163 '__main__',
163 '__main__',
164 '_ssl', # conditional imports in the stdlib, issue1964
164 '_ssl', # conditional imports in the stdlib, issue1964
165 'rfc822',
165 'rfc822',
166 'mimetools',
166 'mimetools',
167 # setuptools 8 expects this module to explode early when not on windows
168 'distutils.msvc9compiler'
167 ]
169 ]
168
170
169 def isenabled():
171 def isenabled():
170 return __builtin__.__import__ == _demandimport
172 return __builtin__.__import__ == _demandimport
171
173
172 def enable():
174 def enable():
173 "enable global demand-loading of modules"
175 "enable global demand-loading of modules"
174 if os.environ.get('HGDEMANDIMPORT') != 'disable':
176 if os.environ.get('HGDEMANDIMPORT') != 'disable':
175 __builtin__.__import__ = _demandimport
177 __builtin__.__import__ = _demandimport
176
178
177 def disable():
179 def disable():
178 "disable global demand-loading of modules"
180 "disable global demand-loading of modules"
179 __builtin__.__import__ = _origimport
181 __builtin__.__import__ = _origimport
@@ -1,45 +1,55 b''
1 from mercurial import demandimport
1 from mercurial import demandimport
2 demandimport.enable()
2 demandimport.enable()
3
3
4 import os
5 if os.name != 'nt':
6 try:
7 import distutils.msvc9compiler
8 print ('distutils.msvc9compiler needs to be an immediate '
9 'importerror on non-windows platforms')
10 distutils.msvc9compiler
11 except ImportError:
12 pass
13
4 import re
14 import re
5
15
6 rsub = re.sub
16 rsub = re.sub
7 def f(obj):
17 def f(obj):
8 l = repr(obj)
18 l = repr(obj)
9 l = rsub("0x[0-9a-fA-F]+", "0x?", l)
19 l = rsub("0x[0-9a-fA-F]+", "0x?", l)
10 l = rsub("from '.*'", "from '?'", l)
20 l = rsub("from '.*'", "from '?'", l)
11 l = rsub("'<[a-z]*>'", "'<whatever>'", l)
21 l = rsub("'<[a-z]*>'", "'<whatever>'", l)
12 return l
22 return l
13
23
14 import os
24 import os
15
25
16 print "os =", f(os)
26 print "os =", f(os)
17 print "os.system =", f(os.system)
27 print "os.system =", f(os.system)
18 print "os =", f(os)
28 print "os =", f(os)
19
29
20 from mercurial import util
30 from mercurial import util
21
31
22 print "util =", f(util)
32 print "util =", f(util)
23 print "util.system =", f(util.system)
33 print "util.system =", f(util.system)
24 print "util =", f(util)
34 print "util =", f(util)
25 print "util.system =", f(util.system)
35 print "util.system =", f(util.system)
26
36
27 import re as fred
37 import re as fred
28 print "fred =", f(fred)
38 print "fred =", f(fred)
29
39
30 import sys as re
40 import sys as re
31 print "re =", f(re)
41 print "re =", f(re)
32
42
33 print "fred =", f(fred)
43 print "fred =", f(fred)
34 print "fred.sub =", f(fred.sub)
44 print "fred.sub =", f(fred.sub)
35 print "fred =", f(fred)
45 print "fred =", f(fred)
36
46
37 print "re =", f(re)
47 print "re =", f(re)
38 print "re.stderr =", f(re.stderr)
48 print "re.stderr =", f(re.stderr)
39 print "re =", f(re)
49 print "re =", f(re)
40
50
41 demandimport.disable()
51 demandimport.disable()
42 os.environ['HGDEMANDIMPORT'] = 'disable'
52 os.environ['HGDEMANDIMPORT'] = 'disable'
43 demandimport.enable()
53 demandimport.enable()
44 from mercurial import node
54 from mercurial import node
45 print "node =", f(node)
55 print "node =", f(node)
General Comments 0
You need to be logged in to leave comments. Login now