##// END OF EJS Templates
demandimport: look for 'mod' suffix as alternative name for module reference...
Yuya Nishihara -
r32447:252d2260 default
parent child Browse files
Show More
@@ -1,302 +1,305 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 from __future__ import absolute_import
27 from __future__ import absolute_import
28
28
29 import contextlib
29 import contextlib
30 import os
30 import os
31 import sys
31 import sys
32
32
33 # __builtin__ in Python 2, builtins in Python 3.
33 # __builtin__ in Python 2, builtins in Python 3.
34 try:
34 try:
35 import __builtin__ as builtins
35 import __builtin__ as builtins
36 except ImportError:
36 except ImportError:
37 import builtins
37 import builtins
38
38
39 contextmanager = contextlib.contextmanager
39 contextmanager = contextlib.contextmanager
40
40
41 _origimport = __import__
41 _origimport = __import__
42
42
43 nothing = object()
43 nothing = object()
44
44
45 # Python 3 doesn't have relative imports nor level -1.
45 # Python 3 doesn't have relative imports nor level -1.
46 level = -1
46 level = -1
47 if sys.version_info[0] >= 3:
47 if sys.version_info[0] >= 3:
48 level = 0
48 level = 0
49 _import = _origimport
49 _import = _origimport
50
50
51 def _hgextimport(importfunc, name, globals, *args, **kwargs):
51 def _hgextimport(importfunc, name, globals, *args, **kwargs):
52 try:
52 try:
53 return importfunc(name, globals, *args, **kwargs)
53 return importfunc(name, globals, *args, **kwargs)
54 except ImportError:
54 except ImportError:
55 if not globals:
55 if not globals:
56 raise
56 raise
57 # extensions are loaded with "hgext_" prefix
57 # extensions are loaded with "hgext_" prefix
58 hgextname = 'hgext_%s' % name
58 hgextname = 'hgext_%s' % name
59 nameroot = hgextname.split('.', 1)[0]
59 nameroot = hgextname.split('.', 1)[0]
60 contextroot = globals.get('__name__', '').split('.', 1)[0]
60 contextroot = globals.get('__name__', '').split('.', 1)[0]
61 if nameroot != contextroot:
61 if nameroot != contextroot:
62 raise
62 raise
63 # retry to import with "hgext_" prefix
63 # retry to import with "hgext_" prefix
64 return importfunc(hgextname, globals, *args, **kwargs)
64 return importfunc(hgextname, globals, *args, **kwargs)
65
65
66 class _demandmod(object):
66 class _demandmod(object):
67 """module demand-loader and proxy
67 """module demand-loader and proxy
68
68
69 Specify 1 as 'level' argument at construction, to import module
69 Specify 1 as 'level' argument at construction, to import module
70 relatively.
70 relatively.
71 """
71 """
72
72
73 def __init__(self, name, globals, locals, level):
73 def __init__(self, name, globals, locals, level):
74 if '.' in name:
74 if '.' in name:
75 head, rest = name.split('.', 1)
75 head, rest = name.split('.', 1)
76 after = [rest]
76 after = [rest]
77 else:
77 else:
78 head = name
78 head = name
79 after = []
79 after = []
80 object.__setattr__(self, r"_data",
80 object.__setattr__(self, r"_data",
81 (head, globals, locals, after, level, set()))
81 (head, globals, locals, after, level, set()))
82 object.__setattr__(self, r"_module", None)
82 object.__setattr__(self, r"_module", None)
83
83
84 def _extend(self, name):
84 def _extend(self, name):
85 """add to the list of submodules to load"""
85 """add to the list of submodules to load"""
86 self._data[3].append(name)
86 self._data[3].append(name)
87
87
88 def _addref(self, name):
88 def _addref(self, name):
89 """Record that the named module ``name`` imports this module.
89 """Record that the named module ``name`` imports this module.
90
90
91 References to this proxy class having the name of this module will be
91 References to this proxy class having the name of this module will be
92 replaced at module load time. We assume the symbol inside the importing
92 replaced at module load time. We assume the symbol inside the importing
93 module is identical to the "head" name of this module. We don't
93 module is identical to the "head" name of this module. We don't
94 actually know if "as X" syntax is being used to change the symbol name
94 actually know if "as X" syntax is being used to change the symbol name
95 because this information isn't exposed to __import__.
95 because this information isn't exposed to __import__.
96 """
96 """
97 self._data[5].add(name)
97 self._data[5].add(name)
98
98
99 def _load(self):
99 def _load(self):
100 if not self._module:
100 if not self._module:
101 head, globals, locals, after, level, modrefs = self._data
101 head, globals, locals, after, level, modrefs = self._data
102 mod = _hgextimport(_import, head, globals, locals, None, level)
102 mod = _hgextimport(_import, head, globals, locals, None, level)
103 if mod is self:
103 if mod is self:
104 # In this case, _hgextimport() above should imply
104 # In this case, _hgextimport() above should imply
105 # _demandimport(). Otherwise, _hgextimport() never
105 # _demandimport(). Otherwise, _hgextimport() never
106 # returns _demandmod. This isn't intentional behavior,
106 # returns _demandmod. This isn't intentional behavior,
107 # in fact. (see also issue5304 for detail)
107 # in fact. (see also issue5304 for detail)
108 #
108 #
109 # If self._module is already bound at this point, self
109 # If self._module is already bound at this point, self
110 # should be already _load()-ed while _hgextimport().
110 # should be already _load()-ed while _hgextimport().
111 # Otherwise, there is no way to import actual module
111 # Otherwise, there is no way to import actual module
112 # as expected, because (re-)invoking _hgextimport()
112 # as expected, because (re-)invoking _hgextimport()
113 # should cause same result.
113 # should cause same result.
114 # This is reason why _load() returns without any more
114 # This is reason why _load() returns without any more
115 # setup but assumes self to be already bound.
115 # setup but assumes self to be already bound.
116 mod = self._module
116 mod = self._module
117 assert mod and mod is not self, "%s, %s" % (self, mod)
117 assert mod and mod is not self, "%s, %s" % (self, mod)
118 return
118 return
119
119
120 # load submodules
120 # load submodules
121 def subload(mod, p):
121 def subload(mod, p):
122 h, t = p, None
122 h, t = p, None
123 if '.' in p:
123 if '.' in p:
124 h, t = p.split('.', 1)
124 h, t = p.split('.', 1)
125 if getattr(mod, h, nothing) is nothing:
125 if getattr(mod, h, nothing) is nothing:
126 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__,
126 setattr(mod, h, _demandmod(p, mod.__dict__, mod.__dict__,
127 level=1))
127 level=1))
128 elif t:
128 elif t:
129 subload(getattr(mod, h), t)
129 subload(getattr(mod, h), t)
130
130
131 for x in after:
131 for x in after:
132 subload(mod, x)
132 subload(mod, x)
133
133
134 # Replace references to this proxy instance with the actual module.
134 # Replace references to this proxy instance with the actual module.
135 if locals and locals.get(head) is self:
135 if locals:
136 locals[head] = mod
136 if locals.get(head) is self:
137 locals[head] = mod
138 elif locals.get(head + r'mod') is self:
139 locals[head + r'mod'] = mod
137
140
138 for modname in modrefs:
141 for modname in modrefs:
139 modref = sys.modules.get(modname, None)
142 modref = sys.modules.get(modname, None)
140 if modref and getattr(modref, head, None) is self:
143 if modref and getattr(modref, head, None) is self:
141 setattr(modref, head, mod)
144 setattr(modref, head, mod)
142
145
143 object.__setattr__(self, r"_module", mod)
146 object.__setattr__(self, r"_module", mod)
144
147
145 def __repr__(self):
148 def __repr__(self):
146 if self._module:
149 if self._module:
147 return "<proxied module '%s'>" % self._data[0]
150 return "<proxied module '%s'>" % self._data[0]
148 return "<unloaded module '%s'>" % self._data[0]
151 return "<unloaded module '%s'>" % self._data[0]
149
152
150 def __call__(self, *args, **kwargs):
153 def __call__(self, *args, **kwargs):
151 raise TypeError("%s object is not callable" % repr(self))
154 raise TypeError("%s object is not callable" % repr(self))
152
155
153 def __getattribute__(self, attr):
156 def __getattribute__(self, attr):
154 if attr in ('_data', '_extend', '_load', '_module', '_addref'):
157 if attr in ('_data', '_extend', '_load', '_module', '_addref'):
155 return object.__getattribute__(self, attr)
158 return object.__getattribute__(self, attr)
156 self._load()
159 self._load()
157 return getattr(self._module, attr)
160 return getattr(self._module, attr)
158
161
159 def __setattr__(self, attr, val):
162 def __setattr__(self, attr, val):
160 self._load()
163 self._load()
161 setattr(self._module, attr, val)
164 setattr(self._module, attr, val)
162
165
163 _pypy = '__pypy__' in sys.builtin_module_names
166 _pypy = '__pypy__' in sys.builtin_module_names
164
167
165 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
168 def _demandimport(name, globals=None, locals=None, fromlist=None, level=level):
166 if locals is None or name in ignore or fromlist == ('*',):
169 if locals is None or name in ignore or fromlist == ('*',):
167 # these cases we can't really delay
170 # these cases we can't really delay
168 return _hgextimport(_import, name, globals, locals, fromlist, level)
171 return _hgextimport(_import, name, globals, locals, fromlist, level)
169 elif not fromlist:
172 elif not fromlist:
170 # import a [as b]
173 # import a [as b]
171 if '.' in name: # a.b
174 if '.' in name: # a.b
172 base, rest = name.split('.', 1)
175 base, rest = name.split('.', 1)
173 # email.__init__ loading email.mime
176 # email.__init__ loading email.mime
174 if globals and globals.get('__name__', None) == base:
177 if globals and globals.get('__name__', None) == base:
175 return _import(name, globals, locals, fromlist, level)
178 return _import(name, globals, locals, fromlist, level)
176 # if a is already demand-loaded, add b to its submodule list
179 # if a is already demand-loaded, add b to its submodule list
177 if base in locals:
180 if base in locals:
178 if isinstance(locals[base], _demandmod):
181 if isinstance(locals[base], _demandmod):
179 locals[base]._extend(rest)
182 locals[base]._extend(rest)
180 return locals[base]
183 return locals[base]
181 return _demandmod(name, globals, locals, level)
184 return _demandmod(name, globals, locals, level)
182 else:
185 else:
183 # There is a fromlist.
186 # There is a fromlist.
184 # from a import b,c,d
187 # from a import b,c,d
185 # from . import b,c,d
188 # from . import b,c,d
186 # from .a import b,c,d
189 # from .a import b,c,d
187
190
188 # level == -1: relative and absolute attempted (Python 2 only).
191 # level == -1: relative and absolute attempted (Python 2 only).
189 # level >= 0: absolute only (Python 2 w/ absolute_import and Python 3).
192 # level >= 0: absolute only (Python 2 w/ absolute_import and Python 3).
190 # The modern Mercurial convention is to use absolute_import everywhere,
193 # The modern Mercurial convention is to use absolute_import everywhere,
191 # so modern Mercurial code will have level >= 0.
194 # so modern Mercurial code will have level >= 0.
192
195
193 # The name of the module the import statement is located in.
196 # The name of the module the import statement is located in.
194 globalname = globals.get('__name__')
197 globalname = globals.get('__name__')
195
198
196 def processfromitem(mod, attr):
199 def processfromitem(mod, attr):
197 """Process an imported symbol in the import statement.
200 """Process an imported symbol in the import statement.
198
201
199 If the symbol doesn't exist in the parent module, and if the
202 If the symbol doesn't exist in the parent module, and if the
200 parent module is a package, it must be a module. We set missing
203 parent module is a package, it must be a module. We set missing
201 modules up as _demandmod instances.
204 modules up as _demandmod instances.
202 """
205 """
203 symbol = getattr(mod, attr, nothing)
206 symbol = getattr(mod, attr, nothing)
204 nonpkg = getattr(mod, '__path__', nothing) is nothing
207 nonpkg = getattr(mod, '__path__', nothing) is nothing
205 if symbol is nothing:
208 if symbol is nothing:
206 if nonpkg:
209 if nonpkg:
207 # do not try relative import, which would raise ValueError,
210 # do not try relative import, which would raise ValueError,
208 # and leave unknown attribute as the default __import__()
211 # and leave unknown attribute as the default __import__()
209 # would do. the missing attribute will be detected later
212 # would do. the missing attribute will be detected later
210 # while processing the import statement.
213 # while processing the import statement.
211 return
214 return
212 mn = '%s.%s' % (mod.__name__, attr)
215 mn = '%s.%s' % (mod.__name__, attr)
213 if mn in ignore:
216 if mn in ignore:
214 importfunc = _origimport
217 importfunc = _origimport
215 else:
218 else:
216 importfunc = _demandmod
219 importfunc = _demandmod
217 symbol = importfunc(attr, mod.__dict__, locals, level=1)
220 symbol = importfunc(attr, mod.__dict__, locals, level=1)
218 setattr(mod, attr, symbol)
221 setattr(mod, attr, symbol)
219
222
220 # Record the importing module references this symbol so we can
223 # Record the importing module references this symbol so we can
221 # replace the symbol with the actual module instance at load
224 # replace the symbol with the actual module instance at load
222 # time.
225 # time.
223 if globalname and isinstance(symbol, _demandmod):
226 if globalname and isinstance(symbol, _demandmod):
224 symbol._addref(globalname)
227 symbol._addref(globalname)
225
228
226 def chainmodules(rootmod, modname):
229 def chainmodules(rootmod, modname):
227 # recurse down the module chain, and return the leaf module
230 # recurse down the module chain, and return the leaf module
228 mod = rootmod
231 mod = rootmod
229 for comp in modname.split('.')[1:]:
232 for comp in modname.split('.')[1:]:
230 if getattr(mod, comp, nothing) is nothing:
233 if getattr(mod, comp, nothing) is nothing:
231 setattr(mod, comp, _demandmod(comp, mod.__dict__,
234 setattr(mod, comp, _demandmod(comp, mod.__dict__,
232 mod.__dict__, level=1))
235 mod.__dict__, level=1))
233 mod = getattr(mod, comp)
236 mod = getattr(mod, comp)
234 return mod
237 return mod
235
238
236 if level >= 0:
239 if level >= 0:
237 if name:
240 if name:
238 # "from a import b" or "from .a import b" style
241 # "from a import b" or "from .a import b" style
239 rootmod = _hgextimport(_origimport, name, globals, locals,
242 rootmod = _hgextimport(_origimport, name, globals, locals,
240 level=level)
243 level=level)
241 mod = chainmodules(rootmod, name)
244 mod = chainmodules(rootmod, name)
242 elif _pypy:
245 elif _pypy:
243 # PyPy's __import__ throws an exception if invoked
246 # PyPy's __import__ throws an exception if invoked
244 # with an empty name and no fromlist. Recreate the
247 # with an empty name and no fromlist. Recreate the
245 # desired behaviour by hand.
248 # desired behaviour by hand.
246 mn = globalname
249 mn = globalname
247 mod = sys.modules[mn]
250 mod = sys.modules[mn]
248 if getattr(mod, '__path__', nothing) is nothing:
251 if getattr(mod, '__path__', nothing) is nothing:
249 mn = mn.rsplit('.', 1)[0]
252 mn = mn.rsplit('.', 1)[0]
250 mod = sys.modules[mn]
253 mod = sys.modules[mn]
251 if level > 1:
254 if level > 1:
252 mn = mn.rsplit('.', level - 1)[0]
255 mn = mn.rsplit('.', level - 1)[0]
253 mod = sys.modules[mn]
256 mod = sys.modules[mn]
254 else:
257 else:
255 mod = _hgextimport(_origimport, name, globals, locals,
258 mod = _hgextimport(_origimport, name, globals, locals,
256 level=level)
259 level=level)
257
260
258 for x in fromlist:
261 for x in fromlist:
259 processfromitem(mod, x)
262 processfromitem(mod, x)
260
263
261 return mod
264 return mod
262
265
263 # But, we still need to support lazy loading of standard library and 3rd
266 # But, we still need to support lazy loading of standard library and 3rd
264 # party modules. So handle level == -1.
267 # party modules. So handle level == -1.
265 mod = _hgextimport(_origimport, name, globals, locals)
268 mod = _hgextimport(_origimport, name, globals, locals)
266 mod = chainmodules(mod, name)
269 mod = chainmodules(mod, name)
267
270
268 for x in fromlist:
271 for x in fromlist:
269 processfromitem(mod, x)
272 processfromitem(mod, x)
270
273
271 return mod
274 return mod
272
275
273 ignore = []
276 ignore = []
274
277
275 def init(ignorelist):
278 def init(ignorelist):
276 global ignore
279 global ignore
277 ignore = ignorelist
280 ignore = ignorelist
278
281
279 def isenabled():
282 def isenabled():
280 return builtins.__import__ == _demandimport
283 return builtins.__import__ == _demandimport
281
284
282 def enable():
285 def enable():
283 "enable global demand-loading of modules"
286 "enable global demand-loading of modules"
284 if os.environ.get('HGDEMANDIMPORT') != 'disable':
287 if os.environ.get('HGDEMANDIMPORT') != 'disable':
285 builtins.__import__ = _demandimport
288 builtins.__import__ = _demandimport
286
289
287 def disable():
290 def disable():
288 "disable global demand-loading of modules"
291 "disable global demand-loading of modules"
289 builtins.__import__ = _origimport
292 builtins.__import__ = _origimport
290
293
291 @contextmanager
294 @contextmanager
292 def deactivated():
295 def deactivated():
293 "context manager for disabling demandimport in 'with' blocks"
296 "context manager for disabling demandimport in 'with' blocks"
294 demandenabled = isenabled()
297 demandenabled = isenabled()
295 if demandenabled:
298 if demandenabled:
296 disable()
299 disable()
297
300
298 try:
301 try:
299 yield
302 yield
300 finally:
303 finally:
301 if demandenabled:
304 if demandenabled:
302 enable()
305 enable()
@@ -1,89 +1,95 b''
1 from __future__ import print_function
1 from __future__ import print_function
2
2
3 from mercurial import demandimport
3 from mercurial import demandimport
4 demandimport.enable()
4 demandimport.enable()
5
5
6 import os
6 import os
7 import subprocess
7 import subprocess
8 import sys
8 import sys
9
9
10 # Only run if demandimport is allowed
10 # Only run if demandimport is allowed
11 if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'],
11 if subprocess.call(['python', '%s/hghave' % os.environ['TESTDIR'],
12 'demandimport']):
12 'demandimport']):
13 sys.exit(80)
13 sys.exit(80)
14
14
15 if os.name != 'nt':
15 if os.name != 'nt':
16 try:
16 try:
17 import distutils.msvc9compiler
17 import distutils.msvc9compiler
18 print('distutils.msvc9compiler needs to be an immediate '
18 print('distutils.msvc9compiler needs to be an immediate '
19 'importerror on non-windows platforms')
19 'importerror on non-windows platforms')
20 distutils.msvc9compiler
20 distutils.msvc9compiler
21 except ImportError:
21 except ImportError:
22 pass
22 pass
23
23
24 import re
24 import re
25
25
26 rsub = re.sub
26 rsub = re.sub
27 def f(obj):
27 def f(obj):
28 l = repr(obj)
28 l = repr(obj)
29 l = rsub("0x[0-9a-fA-F]+", "0x?", l)
29 l = rsub("0x[0-9a-fA-F]+", "0x?", l)
30 l = rsub("from '.*'", "from '?'", l)
30 l = rsub("from '.*'", "from '?'", l)
31 l = rsub("'<[a-z]*>'", "'<whatever>'", l)
31 l = rsub("'<[a-z]*>'", "'<whatever>'", l)
32 return l
32 return l
33
33
34 import os
34 import os
35
35
36 print("os =", f(os))
36 print("os =", f(os))
37 print("os.system =", f(os.system))
37 print("os.system =", f(os.system))
38 print("os =", f(os))
38 print("os =", f(os))
39
39
40 from mercurial import util
40 from mercurial import util
41
41
42 print("util =", f(util))
42 print("util =", f(util))
43 print("util.system =", f(util.system))
43 print("util.system =", f(util.system))
44 print("util =", f(util))
44 print("util =", f(util))
45 print("util.system =", f(util.system))
45 print("util.system =", f(util.system))
46
46
47 from mercurial import hgweb
47 from mercurial import hgweb
48 print("hgweb =", f(hgweb))
48 print("hgweb =", f(hgweb))
49 print("hgweb_mod =", f(hgweb.hgweb_mod))
49 print("hgweb_mod =", f(hgweb.hgweb_mod))
50 print("hgweb =", f(hgweb))
50 print("hgweb =", f(hgweb))
51
51
52 import re as fred
52 import re as fred
53 print("fred =", f(fred))
53 print("fred =", f(fred))
54
54
55 import re as remod
56 print("remod =", f(remod))
57
55 import sys as re
58 import sys as re
56 print("re =", f(re))
59 print("re =", f(re))
57
60
58 print("fred =", f(fred))
61 print("fred =", f(fred))
59 print("fred.sub =", f(fred.sub))
62 print("fred.sub =", f(fred.sub))
60 print("fred =", f(fred))
63 print("fred =", f(fred))
61
64
65 remod.escape # use remod
66 print("remod =", f(remod))
67
62 print("re =", f(re))
68 print("re =", f(re))
63 print("re.stderr =", f(re.stderr))
69 print("re.stderr =", f(re.stderr))
64 print("re =", f(re))
70 print("re =", f(re))
65
71
66 import contextlib
72 import contextlib
67 print("contextlib =", f(contextlib))
73 print("contextlib =", f(contextlib))
68 try:
74 try:
69 from contextlib import unknownattr
75 from contextlib import unknownattr
70 print('no demandmod should be created for attribute of non-package '
76 print('no demandmod should be created for attribute of non-package '
71 'module:\ncontextlib.unknownattr =', f(unknownattr))
77 'module:\ncontextlib.unknownattr =', f(unknownattr))
72 except ImportError as inst:
78 except ImportError as inst:
73 print('contextlib.unknownattr = ImportError: %s'
79 print('contextlib.unknownattr = ImportError: %s'
74 % rsub(r"'", '', str(inst)))
80 % rsub(r"'", '', str(inst)))
75
81
76 # Unlike the import statement, __import__() function should not raise
82 # Unlike the import statement, __import__() function should not raise
77 # ImportError even if fromlist has an unknown item
83 # ImportError even if fromlist has an unknown item
78 # (see Python/import.c:import_module_level() and ensure_fromlist())
84 # (see Python/import.c:import_module_level() and ensure_fromlist())
79 contextlibimp = __import__('contextlib', globals(), locals(), ['unknownattr'])
85 contextlibimp = __import__('contextlib', globals(), locals(), ['unknownattr'])
80 print("__import__('contextlib', ..., ['unknownattr']) =", f(contextlibimp))
86 print("__import__('contextlib', ..., ['unknownattr']) =", f(contextlibimp))
81 print("hasattr(contextlibimp, 'unknownattr') =",
87 print("hasattr(contextlibimp, 'unknownattr') =",
82 util.safehasattr(contextlibimp, 'unknownattr'))
88 util.safehasattr(contextlibimp, 'unknownattr'))
83
89
84 demandimport.disable()
90 demandimport.disable()
85 os.environ['HGDEMANDIMPORT'] = 'disable'
91 os.environ['HGDEMANDIMPORT'] = 'disable'
86 # this enable call should not actually enable demandimport!
92 # this enable call should not actually enable demandimport!
87 demandimport.enable()
93 demandimport.enable()
88 from mercurial import node
94 from mercurial import node
89 print("node =", f(node))
95 print("node =", f(node))
@@ -1,23 +1,25 b''
1 os = <unloaded module 'os'>
1 os = <unloaded module 'os'>
2 os.system = <built-in function system>
2 os.system = <built-in function system>
3 os = <module 'os' from '?'>
3 os = <module 'os' from '?'>
4 util = <unloaded module 'util'>
4 util = <unloaded module 'util'>
5 util.system = <function system at 0x?>
5 util.system = <function system at 0x?>
6 util = <module 'mercurial.util' from '?'>
6 util = <module 'mercurial.util' from '?'>
7 util.system = <function system at 0x?>
7 util.system = <function system at 0x?>
8 hgweb = <unloaded module 'hgweb'>
8 hgweb = <unloaded module 'hgweb'>
9 hgweb_mod = <unloaded module 'hgweb_mod'>
9 hgweb_mod = <unloaded module 'hgweb_mod'>
10 hgweb = <module 'mercurial.hgweb' from '?'>
10 hgweb = <module 'mercurial.hgweb' from '?'>
11 fred = <unloaded module 're'>
11 fred = <unloaded module 're'>
12 remod = <unloaded module 're'>
12 re = <unloaded module 'sys'>
13 re = <unloaded module 'sys'>
13 fred = <unloaded module 're'>
14 fred = <unloaded module 're'>
14 fred.sub = <function sub at 0x?>
15 fred.sub = <function sub at 0x?>
15 fred = <proxied module 're'>
16 fred = <proxied module 're'>
17 remod = <module 're' from '?'>
16 re = <unloaded module 'sys'>
18 re = <unloaded module 'sys'>
17 re.stderr = <open file '<whatever>', mode 'w' at 0x?>
19 re.stderr = <open file '<whatever>', mode 'w' at 0x?>
18 re = <proxied module 'sys'>
20 re = <proxied module 'sys'>
19 contextlib = <unloaded module 'contextlib'>
21 contextlib = <unloaded module 'contextlib'>
20 contextlib.unknownattr = ImportError: cannot import name unknownattr
22 contextlib.unknownattr = ImportError: cannot import name unknownattr
21 __import__('contextlib', ..., ['unknownattr']) = <module 'contextlib' from '?'>
23 __import__('contextlib', ..., ['unknownattr']) = <module 'contextlib' from '?'>
22 hasattr(contextlibimp, 'unknownattr') = False
24 hasattr(contextlibimp, 'unknownattr') = False
23 node = <module 'mercurial.node' from '?'>
25 node = <module 'mercurial.node' from '?'>
General Comments 0
You need to be logged in to leave comments. Login now