8
8
from zope.interface import Interface, implements
11
_sysModulesSpecialCases = {"os": ['path']}
15
15
print ' '.join(str(x) for x in args)
18
def proxyModule(original, **replacements):
20
Create a proxy for a module object, overriding some of its attributes with
23
@param original: A module.
24
@param replacements: Attribute names and objects to associate with them.
26
@returns: A module proxy with attributes containing the replacement
27
objects; other attribute accesses are delegated to the original module.
29
class _ModuleProxy(object):
30
def __getattribute__(self, name):
31
if name in replacements:
32
return replacements[name]
34
return getattr(original, name)
37
return "<Proxy for %r: %s replaced>" % (
38
original, ', '.join(replacements.keys()))
42
def redirectLocalImports(name, globals=None, *a, **kw):
44
Catch function-level imports in modules loaded via Exocet. This ensures
45
that any imports done after module load time look up imported names in the
46
same context the module was originally loaded in.
49
if globals is not None:
50
mf = globals.get('__exocet_context__', None)
52
trace("__import__ of", name, "called in exocet module", mf, mf.mapper)
53
return _isolateImports(mf, _originalImport, name, globals, *a, **kw)
55
return _originalImport(name, globals, *a, **kw)
57
return _originalImport(name, globals, *a, **kw)
60
_originalImport = None
62
def installExocetGlobalHook():
64
Install the global Exocet import hook.
66
global _originalImport
67
_originalImport = __builtin__.__import__
68
__builtin__.__import__ = redirectLocalImports
72
def uninstallExocetGlobalHook():
73
__builtin__.__import__ = _originalImport
76
installExocetGlobalHook()
78
18
class IMapper(Interface):
80
20
An object that maps names used in C{import} statements to objects (such as
274
214
sys.modules.clear()
275
215
sys.modules.update(self._oldSysModules)
276
216
topLevel = _originalImport(name)
217
trace("pep302Mapper imported %r as %r@%d" % (name, topLevel, id(topLevel)))
277
218
packages = name.split(".")[1:]
220
trace("subelements:", packages)
279
221
for p in packages:
222
trace("getattr", m, p)
280
223
m = getattr(m, p)
224
trace("done:", m, id(m))
227
self._oldSysModules.update(sys.modules)
283
228
sys.meta_path[:] = prevMetaPath
284
229
sys.modules.clear()
285
230
sys.modules.update(prevSysModules)
325
270
trace("load_module", fqn)
326
271
trace("sys.modules", sys.modules)
327
272
p = self.mapper.lookup(fqn)
273
trace("load_module", fqn , "done", id(p))
275
if fqn in _sysModulesSpecialCases:
276
# This module didn't have access to our isolated sys.modules when it
277
# did its sys.modules modification. Replicate it here.
278
for submoduleName in _sysModulesSpecialCases[fqn]:
279
subfqn = '.'.join([fqn, submoduleName])
280
sys.modules[subfqn] = getattr(p, submoduleName, None)
333
286
Wrapper around C{__import__}. Needed to ensure builtin modules aren't
334
287
loaded from the global context.
336
trace("Import invoked:", name)
289
trace("Import invoked:", name, kwargs.keys())
337
290
if name in sys.builtin_module_names:
338
291
trace("Loading builtin module", name)
339
292
return self.load_module(name)
697
650
return topological_sort(component_graph)
654
def proxyModule(original, **replacements):
656
Create a proxy for a module object, overriding some of its attributes with
659
@param original: A module.
660
@param replacements: Attribute names and objects to associate with them.
662
@returns: A module proxy with attributes containing the replacement
663
objects; other attribute accesses are delegated to the original module.
665
class _ModuleProxy(object):
666
def __getattribute__(self, name):
667
if name in replacements:
668
return replacements[name]
670
return getattr(original, name)
673
return "<Proxy for %r: %s replaced>" % (
674
original, ', '.join(replacements.keys()))
675
return _ModuleProxy()
678
def redirectLocalImports(name, globals=None, *a, **kw):
680
Catch function-level imports in modules loaded via Exocet. This ensures
681
that any imports done after module load time look up imported names in the
682
same context the module was originally loaded in.
685
if globals is not None:
686
mf = globals.get('__exocet_context__', None)
688
trace("isolated __import__ of", name, "called in exocet module", mf, mf.mapper)
689
return _isolateImports(mf, _originalImport, name, globals, *a, **kw)
691
return _originalImport(name, globals, *a, **kw)
693
return _originalImport(name, globals, *a, **kw)
696
_originalImport = None
698
def installExocetGlobalHook():
700
Install the global Exocet import hook.
702
global _originalImport
703
_originalImport = __builtin__.__import__
704
__builtin__.__import__ = redirectLocalImports
708
def uninstallExocetGlobalHook():
709
__builtin__.__import__ = _originalImport
712
installExocetGlobalHook()