mirror of
https://github.com/python/cpython.git
synced 2025-09-27 18:59:43 +00:00
The ihooks module has been removed.
This commit is contained in:
parent
4fabdc7a63
commit
bd474420e2
5 changed files with 3 additions and 526 deletions
|
@ -22,8 +22,7 @@ are always available. They are listed here in alphabetical order.
|
||||||
The function is invoked by the :keyword:`import` statement. It mainly exists
|
The function is invoked by the :keyword:`import` statement. It mainly exists
|
||||||
so that you can replace it with another function that has a compatible
|
so that you can replace it with another function that has a compatible
|
||||||
interface, in order to change the semantics of the :keyword:`import`
|
interface, in order to change the semantics of the :keyword:`import`
|
||||||
statement. For examples of why and how you would do this, see the standard
|
statement. See also the built-in module :mod:`imp`, which
|
||||||
library module :mod:`ihooks`. See also the built-in module :mod:`imp`, which
|
|
||||||
defines some useful operations out of which you can build your own
|
defines some useful operations out of which you can build your own
|
||||||
:func:`__import__` function.
|
:func:`__import__` function.
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,6 @@ Fredrik Lundh; the specific contents of this chapter have been substantially
|
||||||
revised.
|
revised.
|
||||||
|
|
||||||
|
|
||||||
Miscellaneous useful utilities
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Some of these are very old and/or not very robust; marked with "hmm."
|
|
||||||
|
|
||||||
:mod:`ihooks`
|
|
||||||
--- Import hook support (for :mod:`rexec`; may become obsolete).
|
|
||||||
|
|
||||||
|
|
||||||
Platform specific modules
|
Platform specific modules
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|
514
Lib/ihooks.py
514
Lib/ihooks.py
|
@ -1,514 +0,0 @@
|
||||||
"""Import hook support.
|
|
||||||
|
|
||||||
Consistent use of this module will make it possible to change the
|
|
||||||
different mechanisms involved in loading modules independently.
|
|
||||||
|
|
||||||
While the built-in module imp exports interfaces to the built-in
|
|
||||||
module searching and loading algorithm, and it is possible to replace
|
|
||||||
the built-in function __import__ in order to change the semantics of
|
|
||||||
the import statement, until now it has been difficult to combine the
|
|
||||||
effect of different __import__ hacks, like loading modules from URLs
|
|
||||||
by rimport.py.
|
|
||||||
|
|
||||||
This module defines three new concepts:
|
|
||||||
|
|
||||||
1) A "file system hooks" class provides an interface to a filesystem.
|
|
||||||
|
|
||||||
One hooks class is defined (Hooks), which uses the interface provided
|
|
||||||
by standard modules os and os.path. It should be used as the base
|
|
||||||
class for other hooks classes.
|
|
||||||
|
|
||||||
2) A "module loader" class provides an interface to search for a
|
|
||||||
module in a search path and to load it. It defines a method which
|
|
||||||
searches for a module in a single directory; by overriding this method
|
|
||||||
one can redefine the details of the search. If the directory is None,
|
|
||||||
built-in and frozen modules are searched instead.
|
|
||||||
|
|
||||||
Two module loader class are defined, both implementing the search
|
|
||||||
strategy used by the built-in __import__ function: ModuleLoader uses
|
|
||||||
the imp module's find_module interface, while HookableModuleLoader
|
|
||||||
uses a file system hooks class to interact with the file system. Both
|
|
||||||
use the imp module's load_* interfaces to actually load the module.
|
|
||||||
|
|
||||||
3) A "module importer" class provides an interface to import a
|
|
||||||
module, as well as interfaces to reload and unload a module. It also
|
|
||||||
provides interfaces to install and uninstall itself instead of the
|
|
||||||
default __import__ and reload (and unload) functions.
|
|
||||||
|
|
||||||
One module importer class is defined (ModuleImporter), which uses a
|
|
||||||
module loader instance passed in (by default HookableModuleLoader is
|
|
||||||
instantiated).
|
|
||||||
|
|
||||||
The classes defined here should be used as base classes for extended
|
|
||||||
functionality along those lines.
|
|
||||||
|
|
||||||
If a module importer class supports dotted names, its import_module()
|
|
||||||
must return a different value depending on whether it is called on
|
|
||||||
behalf of a "from ... import ..." statement or not. (This is caused
|
|
||||||
by the way the __import__ hook is used by the Python interpreter.)
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
import builtins
|
|
||||||
import imp
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
__all__ = ["BasicModuleLoader","Hooks","ModuleLoader","FancyModuleLoader",
|
|
||||||
"BasicModuleImporter","ModuleImporter","install","uninstall"]
|
|
||||||
|
|
||||||
VERBOSE = 0
|
|
||||||
|
|
||||||
|
|
||||||
from imp import C_EXTENSION, PY_SOURCE, PY_COMPILED
|
|
||||||
from imp import C_BUILTIN, PY_FROZEN, PKG_DIRECTORY
|
|
||||||
BUILTIN_MODULE = C_BUILTIN
|
|
||||||
FROZEN_MODULE = PY_FROZEN
|
|
||||||
|
|
||||||
|
|
||||||
class _Verbose:
|
|
||||||
|
|
||||||
def __init__(self, verbose = VERBOSE):
|
|
||||||
self.verbose = verbose
|
|
||||||
|
|
||||||
def get_verbose(self):
|
|
||||||
return self.verbose
|
|
||||||
|
|
||||||
def set_verbose(self, verbose):
|
|
||||||
self.verbose = verbose
|
|
||||||
|
|
||||||
# XXX The following is an experimental interface
|
|
||||||
|
|
||||||
def note(self, *args):
|
|
||||||
if self.verbose:
|
|
||||||
self.message(*args)
|
|
||||||
|
|
||||||
def message(self, format, *args):
|
|
||||||
if args:
|
|
||||||
print(format%args)
|
|
||||||
else:
|
|
||||||
print(format)
|
|
||||||
|
|
||||||
|
|
||||||
class BasicModuleLoader(_Verbose):
|
|
||||||
|
|
||||||
"""Basic module loader.
|
|
||||||
|
|
||||||
This provides the same functionality as built-in import. It
|
|
||||||
doesn't deal with checking sys.modules -- all it provides is
|
|
||||||
find_module() and a load_module(), as well as find_module_in_dir()
|
|
||||||
which searches just one directory, and can be overridden by a
|
|
||||||
derived class to change the module search algorithm when the basic
|
|
||||||
dependency on sys.path is unchanged.
|
|
||||||
|
|
||||||
The interface is a little more convenient than imp's:
|
|
||||||
find_module(name, [path]) returns None or 'stuff', and
|
|
||||||
load_module(name, stuff) loads the module.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def find_module(self, name, path = None):
|
|
||||||
if path is None:
|
|
||||||
path = [None] + self.default_path()
|
|
||||||
for dir in path:
|
|
||||||
stuff = self.find_module_in_dir(name, dir)
|
|
||||||
if stuff: return stuff
|
|
||||||
return None
|
|
||||||
|
|
||||||
def default_path(self):
|
|
||||||
return sys.path
|
|
||||||
|
|
||||||
def find_module_in_dir(self, name, dir):
|
|
||||||
if dir is None:
|
|
||||||
return self.find_builtin_module(name)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
return imp.find_module(name, [dir])
|
|
||||||
except ImportError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_builtin_module(self, name):
|
|
||||||
# XXX frozen packages?
|
|
||||||
if imp.is_builtin(name):
|
|
||||||
return None, '', ('', '', BUILTIN_MODULE)
|
|
||||||
if imp.is_frozen(name):
|
|
||||||
return None, '', ('', '', FROZEN_MODULE)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def load_module(self, name, stuff):
|
|
||||||
file, filename, info = stuff
|
|
||||||
try:
|
|
||||||
return imp.load_module(name, file, filename, info)
|
|
||||||
finally:
|
|
||||||
if file: file.close()
|
|
||||||
|
|
||||||
|
|
||||||
class Hooks(_Verbose):
|
|
||||||
|
|
||||||
"""Hooks into the filesystem and interpreter.
|
|
||||||
|
|
||||||
By deriving a subclass you can redefine your filesystem interface,
|
|
||||||
e.g. to merge it with the URL space.
|
|
||||||
|
|
||||||
This base class behaves just like the native filesystem.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# imp interface
|
|
||||||
def get_suffixes(self): return imp.get_suffixes()
|
|
||||||
def new_module(self, name): return imp.new_module(name)
|
|
||||||
def is_builtin(self, name): return imp.is_builtin(name)
|
|
||||||
def init_builtin(self, name): return imp.init_builtin(name)
|
|
||||||
def is_frozen(self, name): return imp.is_frozen(name)
|
|
||||||
def init_frozen(self, name): return imp.init_frozen(name)
|
|
||||||
def get_frozen_object(self, name): return imp.get_frozen_object(name)
|
|
||||||
def load_source(self, name, filename, file=None):
|
|
||||||
return imp.load_source(name, filename, file)
|
|
||||||
def load_compiled(self, name, filename, file=None):
|
|
||||||
return imp.load_compiled(name, filename, file)
|
|
||||||
def load_dynamic(self, name, filename, file=None):
|
|
||||||
return imp.load_dynamic(name, filename, file)
|
|
||||||
def load_package(self, name, filename, file=None):
|
|
||||||
return imp.load_module(name, file, filename, ("", "", PKG_DIRECTORY))
|
|
||||||
|
|
||||||
def add_module(self, name):
|
|
||||||
d = self.modules_dict()
|
|
||||||
if name in d: return d[name]
|
|
||||||
d[name] = m = self.new_module(name)
|
|
||||||
return m
|
|
||||||
|
|
||||||
# sys interface
|
|
||||||
def modules_dict(self): return sys.modules
|
|
||||||
def default_path(self): return sys.path
|
|
||||||
|
|
||||||
def path_split(self, x): return os.path.split(x)
|
|
||||||
def path_join(self, x, y): return os.path.join(x, y)
|
|
||||||
def path_isabs(self, x): return os.path.isabs(x)
|
|
||||||
# etc.
|
|
||||||
|
|
||||||
def path_exists(self, x): return os.path.exists(x)
|
|
||||||
def path_isdir(self, x): return os.path.isdir(x)
|
|
||||||
def path_isfile(self, x): return os.path.isfile(x)
|
|
||||||
def path_islink(self, x): return os.path.islink(x)
|
|
||||||
# etc.
|
|
||||||
|
|
||||||
def openfile(self, *x): return open(*x)
|
|
||||||
openfile_error = IOError
|
|
||||||
def listdir(self, x): return os.listdir(x)
|
|
||||||
listdir_error = os.error
|
|
||||||
# etc.
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleLoader(BasicModuleLoader):
|
|
||||||
|
|
||||||
"""Default module loader; uses file system hooks.
|
|
||||||
|
|
||||||
By defining suitable hooks, you might be able to load modules from
|
|
||||||
other sources than the file system, e.g. from compressed or
|
|
||||||
encrypted files, tar files or (if you're brave!) URLs.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, hooks = None, verbose = VERBOSE):
|
|
||||||
BasicModuleLoader.__init__(self, verbose)
|
|
||||||
self.hooks = hooks or Hooks(verbose)
|
|
||||||
|
|
||||||
def default_path(self):
|
|
||||||
return self.hooks.default_path()
|
|
||||||
|
|
||||||
def modules_dict(self):
|
|
||||||
return self.hooks.modules_dict()
|
|
||||||
|
|
||||||
def get_hooks(self):
|
|
||||||
return self.hooks
|
|
||||||
|
|
||||||
def set_hooks(self, hooks):
|
|
||||||
self.hooks = hooks
|
|
||||||
|
|
||||||
def find_builtin_module(self, name):
|
|
||||||
# XXX frozen packages?
|
|
||||||
if self.hooks.is_builtin(name):
|
|
||||||
return None, '', ('', '', BUILTIN_MODULE)
|
|
||||||
if self.hooks.is_frozen(name):
|
|
||||||
return None, '', ('', '', FROZEN_MODULE)
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_module_in_dir(self, name, dir, allow_packages=1):
|
|
||||||
if dir is None:
|
|
||||||
return self.find_builtin_module(name)
|
|
||||||
if allow_packages:
|
|
||||||
fullname = self.hooks.path_join(dir, name)
|
|
||||||
if self.hooks.path_isdir(fullname):
|
|
||||||
stuff = self.find_module_in_dir("__init__", fullname, 0)
|
|
||||||
if stuff:
|
|
||||||
file = stuff[0]
|
|
||||||
if file: file.close()
|
|
||||||
return None, fullname, ('', '', PKG_DIRECTORY)
|
|
||||||
for info in self.hooks.get_suffixes():
|
|
||||||
suff, mode, type = info
|
|
||||||
fullname = self.hooks.path_join(dir, name+suff)
|
|
||||||
try:
|
|
||||||
fp = self.hooks.openfile(fullname, mode)
|
|
||||||
return fp, fullname, info
|
|
||||||
except self.hooks.openfile_error:
|
|
||||||
pass
|
|
||||||
return None
|
|
||||||
|
|
||||||
def load_module(self, name, stuff):
|
|
||||||
file, filename, info = stuff
|
|
||||||
(suff, mode, type) = info
|
|
||||||
try:
|
|
||||||
if type == BUILTIN_MODULE:
|
|
||||||
return self.hooks.init_builtin(name)
|
|
||||||
if type == FROZEN_MODULE:
|
|
||||||
return self.hooks.init_frozen(name)
|
|
||||||
if type == C_EXTENSION:
|
|
||||||
m = self.hooks.load_dynamic(name, filename, file)
|
|
||||||
elif type == PY_SOURCE:
|
|
||||||
m = self.hooks.load_source(name, filename, file)
|
|
||||||
elif type == PY_COMPILED:
|
|
||||||
m = self.hooks.load_compiled(name, filename, file)
|
|
||||||
elif type == PKG_DIRECTORY:
|
|
||||||
m = self.hooks.load_package(name, filename, file)
|
|
||||||
else:
|
|
||||||
raise ImportError("Unrecognized module type (%r) for %s"
|
|
||||||
% (type, name))
|
|
||||||
finally:
|
|
||||||
if file: file.close()
|
|
||||||
m.__file__ = filename
|
|
||||||
return m
|
|
||||||
|
|
||||||
|
|
||||||
class FancyModuleLoader(ModuleLoader):
|
|
||||||
|
|
||||||
"""Fancy module loader -- parses and execs the code itself."""
|
|
||||||
|
|
||||||
def load_module(self, name, stuff):
|
|
||||||
file, filename, (suff, mode, type) = stuff
|
|
||||||
realfilename = filename
|
|
||||||
path = None
|
|
||||||
|
|
||||||
if type == PKG_DIRECTORY:
|
|
||||||
initstuff = self.find_module_in_dir("__init__", filename, 0)
|
|
||||||
if not initstuff:
|
|
||||||
raise ImportError("No __init__ module in package %s" % name)
|
|
||||||
initfile, initfilename, initinfo = initstuff
|
|
||||||
initsuff, initmode, inittype = initinfo
|
|
||||||
if inittype not in (PY_COMPILED, PY_SOURCE):
|
|
||||||
if initfile: initfile.close()
|
|
||||||
raise ImportError("Bad type (%r) for __init__ module"
|
|
||||||
" in package %s" % (inittype, name))
|
|
||||||
path = [filename]
|
|
||||||
file = initfile
|
|
||||||
realfilename = initfilename
|
|
||||||
type = inittype
|
|
||||||
|
|
||||||
if type == FROZEN_MODULE:
|
|
||||||
code = self.hooks.get_frozen_object(name)
|
|
||||||
elif type == PY_COMPILED:
|
|
||||||
import marshal
|
|
||||||
file.seek(8)
|
|
||||||
code = marshal.load(file)
|
|
||||||
elif type == PY_SOURCE:
|
|
||||||
data = file.read()
|
|
||||||
code = compile(data, realfilename, 'exec')
|
|
||||||
else:
|
|
||||||
return ModuleLoader.load_module(self, name, stuff)
|
|
||||||
|
|
||||||
m = self.hooks.add_module(name)
|
|
||||||
if path:
|
|
||||||
m.__path__ = path
|
|
||||||
m.__file__ = filename
|
|
||||||
try:
|
|
||||||
exec(code, m.__dict__)
|
|
||||||
except:
|
|
||||||
d = self.hooks.modules_dict()
|
|
||||||
if name in d:
|
|
||||||
del d[name]
|
|
||||||
raise
|
|
||||||
return m
|
|
||||||
|
|
||||||
|
|
||||||
class BasicModuleImporter(_Verbose):
|
|
||||||
|
|
||||||
"""Basic module importer; uses module loader.
|
|
||||||
|
|
||||||
This provides basic import facilities but no package imports.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, loader = None, verbose = VERBOSE):
|
|
||||||
_Verbose.__init__(self, verbose)
|
|
||||||
self.loader = loader or ModuleLoader(None, verbose)
|
|
||||||
self.modules = self.loader.modules_dict()
|
|
||||||
|
|
||||||
def get_loader(self):
|
|
||||||
return self.loader
|
|
||||||
|
|
||||||
def set_loader(self, loader):
|
|
||||||
self.loader = loader
|
|
||||||
|
|
||||||
def get_hooks(self):
|
|
||||||
return self.loader.get_hooks()
|
|
||||||
|
|
||||||
def set_hooks(self, hooks):
|
|
||||||
return self.loader.set_hooks(hooks)
|
|
||||||
|
|
||||||
def import_module(self, name, globals={}, locals={}, fromlist=[]):
|
|
||||||
name = str(name)
|
|
||||||
if name in self.modules:
|
|
||||||
return self.modules[name] # Fast path
|
|
||||||
stuff = self.loader.find_module(name)
|
|
||||||
if not stuff:
|
|
||||||
raise ImportError("No module named %s" % name)
|
|
||||||
return self.loader.load_module(name, stuff)
|
|
||||||
|
|
||||||
def reload(self, module, path = None):
|
|
||||||
name = str(module.__name__)
|
|
||||||
stuff = self.loader.find_module(name, path)
|
|
||||||
if not stuff:
|
|
||||||
raise ImportError("Module %s not found for reload" % name)
|
|
||||||
return self.loader.load_module(name, stuff)
|
|
||||||
|
|
||||||
def unload(self, module):
|
|
||||||
del self.modules[str(module.__name__)]
|
|
||||||
# XXX Should this try to clear the module's namespace?
|
|
||||||
|
|
||||||
def install(self):
|
|
||||||
self.save_import_module = builtins.__import__
|
|
||||||
if not hasattr(builtins, 'unload'):
|
|
||||||
builtins.unload = None
|
|
||||||
self.save_unload = builtins.unload
|
|
||||||
builtins.__import__ = self.import_module
|
|
||||||
builtins.unload = self.unload
|
|
||||||
|
|
||||||
def uninstall(self):
|
|
||||||
builtins.__import__ = self.save_import_module
|
|
||||||
builtins.unload = self.save_unload
|
|
||||||
if not builtins.unload:
|
|
||||||
del builtins.unload
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleImporter(BasicModuleImporter):
|
|
||||||
|
|
||||||
"""A module importer that supports packages."""
|
|
||||||
|
|
||||||
def import_module(self, name, globals=None, locals=None, fromlist=None):
|
|
||||||
parent = self.determine_parent(globals)
|
|
||||||
q, tail = self.find_head_package(parent, str(name))
|
|
||||||
m = self.load_tail(q, tail)
|
|
||||||
if not fromlist:
|
|
||||||
return q
|
|
||||||
if hasattr(m, "__path__"):
|
|
||||||
self.ensure_fromlist(m, fromlist)
|
|
||||||
return m
|
|
||||||
|
|
||||||
def determine_parent(self, globals):
|
|
||||||
if not globals or not "__name__" in globals:
|
|
||||||
return None
|
|
||||||
pname = globals['__name__']
|
|
||||||
if "__path__" in globals:
|
|
||||||
parent = self.modules[pname]
|
|
||||||
assert globals is parent.__dict__
|
|
||||||
return parent
|
|
||||||
if '.' in pname:
|
|
||||||
i = pname.rfind('.')
|
|
||||||
pname = pname[:i]
|
|
||||||
parent = self.modules[pname]
|
|
||||||
assert parent.__name__ == pname
|
|
||||||
return parent
|
|
||||||
return None
|
|
||||||
|
|
||||||
def find_head_package(self, parent, name):
|
|
||||||
if '.' in name:
|
|
||||||
i = name.find('.')
|
|
||||||
head = name[:i]
|
|
||||||
tail = name[i+1:]
|
|
||||||
else:
|
|
||||||
head = name
|
|
||||||
tail = ""
|
|
||||||
if parent:
|
|
||||||
qname = "%s.%s" % (parent.__name__, head)
|
|
||||||
else:
|
|
||||||
qname = head
|
|
||||||
q = self.import_it(head, qname, parent)
|
|
||||||
if q: return q, tail
|
|
||||||
if parent:
|
|
||||||
qname = head
|
|
||||||
parent = None
|
|
||||||
q = self.import_it(head, qname, parent)
|
|
||||||
if q: return q, tail
|
|
||||||
raise ImportError("No module named " + qname)
|
|
||||||
|
|
||||||
def load_tail(self, q, tail):
|
|
||||||
m = q
|
|
||||||
while tail:
|
|
||||||
i = tail.find('.')
|
|
||||||
if i < 0: i = len(tail)
|
|
||||||
head, tail = tail[:i], tail[i+1:]
|
|
||||||
mname = "%s.%s" % (m.__name__, head)
|
|
||||||
m = self.import_it(head, mname, m)
|
|
||||||
if not m:
|
|
||||||
raise ImportError("No module named " + mname)
|
|
||||||
return m
|
|
||||||
|
|
||||||
def ensure_fromlist(self, m, fromlist, recursive=0):
|
|
||||||
for sub in fromlist:
|
|
||||||
if sub == "*":
|
|
||||||
if not recursive:
|
|
||||||
try:
|
|
||||||
all = m.__all__
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.ensure_fromlist(m, all, 1)
|
|
||||||
continue
|
|
||||||
if sub != "*" and not hasattr(m, sub):
|
|
||||||
subname = "%s.%s" % (m.__name__, sub)
|
|
||||||
submod = self.import_it(sub, subname, m)
|
|
||||||
if not submod:
|
|
||||||
raise ImportError("No module named " + subname)
|
|
||||||
|
|
||||||
def import_it(self, partname, fqname, parent, force_load=0):
|
|
||||||
if not partname:
|
|
||||||
raise ValueError("Empty module name")
|
|
||||||
if not force_load:
|
|
||||||
try:
|
|
||||||
return self.modules[fqname]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
path = parent and parent.__path__
|
|
||||||
except AttributeError:
|
|
||||||
return None
|
|
||||||
partname = str(partname)
|
|
||||||
stuff = self.loader.find_module(partname, path)
|
|
||||||
if not stuff:
|
|
||||||
return None
|
|
||||||
fqname = str(fqname)
|
|
||||||
m = self.loader.load_module(fqname, stuff)
|
|
||||||
if parent:
|
|
||||||
setattr(parent, partname, m)
|
|
||||||
return m
|
|
||||||
|
|
||||||
def reload(self, module):
|
|
||||||
name = str(module.__name__)
|
|
||||||
if '.' not in name:
|
|
||||||
return self.import_it(name, name, None, force_load=1)
|
|
||||||
i = name.rfind('.')
|
|
||||||
pname = name[:i]
|
|
||||||
parent = self.modules[pname]
|
|
||||||
return self.import_it(name[i+1:], name, parent, force_load=1)
|
|
||||||
|
|
||||||
|
|
||||||
default_importer = None
|
|
||||||
current_importer = None
|
|
||||||
|
|
||||||
def install(importer = None):
|
|
||||||
global current_importer
|
|
||||||
current_importer = importer or default_importer or ModuleImporter()
|
|
||||||
current_importer.install()
|
|
||||||
|
|
||||||
def uninstall():
|
|
||||||
global current_importer
|
|
||||||
current_importer.uninstall()
|
|
|
@ -49,7 +49,6 @@ class TestUntestedModules(unittest.TestCase):
|
||||||
import formatter
|
import formatter
|
||||||
import getpass
|
import getpass
|
||||||
import htmlentitydefs
|
import htmlentitydefs
|
||||||
import ihooks
|
|
||||||
import imghdr
|
import imghdr
|
||||||
import keyword
|
import keyword
|
||||||
import linecache
|
import linecache
|
||||||
|
|
|
@ -21,6 +21,8 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- The ihooks module has been removed.
|
||||||
|
|
||||||
- The fpformat module has been removed.
|
- The fpformat module has been removed.
|
||||||
|
|
||||||
- The dircache module has been removed.
|
- The dircache module has been removed.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue