4
# Demonstration subclasses of imputil.Importer
7
# There should be consideration for the imports below if it is desirable
8
# to have "all" modules be imported through the imputil system.
10
# these are C extensions
16
# these are .py modules
20
######################################################################
23
_StringType = type('')
25
######################################################################
27
# byte-compiled file suffic character
28
_suffix_char = __debug__ and 'c' or 'o'
30
# byte-compiled file suffix
31
_suffix = '.py' + _suffix_char
33
# the C_EXTENSION suffixes
34
_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())
36
def _timestamp(pathname):
37
"Return the file modification time as a Long."
44
def _fs_import(dir, modname, fqname):
45
"Fetch a module from the filesystem."
47
pathname = os.path.join(dir, modname)
48
if os.path.isdir(pathname):
49
values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
51
pathname = os.path.join(pathname, '__init__')
56
# look for dynload modules
57
for desc in _c_suffixes:
58
file = pathname + desc[0]
60
fp = open(file, desc[1])
64
module = imp.load_module(fqname, fp, file, desc)
65
values['__file__'] = file
66
return 0, module, values
68
t_py = _timestamp(pathname + '.py')
69
t_pyc = _timestamp(pathname + _suffix)
70
if t_py is None and t_pyc is None:
73
if t_py is None or (t_pyc is not None and t_pyc >= t_py):
74
file = pathname + _suffix
76
if f.read(4) == imp.get_magic():
77
t = struct.unpack('<I', f.read(4))[0]
79
code = marshal.load(f)
82
file = pathname + '.py'
83
code = _compile(file, t_py)
85
values['__file__'] = file
86
return ispkg, code, values
88
######################################################################
90
# Simple function-based importer
92
class FuncImporter(imputil.Importer):
93
"Importer subclass to delegate to a function rather than method overrides."
94
def __init__(self, func):
96
def get_code(self, parent, modname, fqname):
97
return self.func(parent, modname, fqname)
99
def install_with(func):
100
FuncImporter(func).install()
103
######################################################################
105
# Base class for archive-based importing
107
class PackageArchiveImporter(imputil.Importer):
108
"""Importer subclass to import from (file) archives.
110
This Importer handles imports of the style <archive>.<subfile>, where
111
<archive> can be located using a subclass-specific mechanism and the
112
<subfile> is found in the archive using a subclass-specific mechanism.
114
This class defines two hooks for subclasses: one to locate an archive
115
(and possibly return some context for future subfile lookups), and one
119
def get_code(self, parent, modname, fqname):
121
# the Importer._finish_import logic ensures that we handle imports
122
# under the top level module (package / archive).
123
assert parent.__importer__ == self
125
# if a parent "package" is provided, then we are importing a
126
# sub-file from the archive.
127
result = self.get_subfile(parent.__archive__, modname)
130
if isinstance(result, _TupleType):
131
assert len(result) == 2
135
# no parent was provided, so the archive should exist somewhere on the
137
archive = self.get_archive(modname)
140
return 1, "", {'__archive__':archive}
142
def get_archive(self, modname):
143
"""Get an archive of modules.
145
This method should locate an archive and return a value which can be
146
used by get_subfile to load modules from it. The value may be a simple
147
pathname, an open file, or a complex object that caches information
150
Return None if the archive was not found.
152
raise RuntimeError, "get_archive not implemented"
154
def get_subfile(self, archive, modname):
155
"""Get code from a subfile in the specified archive.
157
Given the specified archive (as returned by get_archive()), locate
158
and return a code object for the specified module name.
160
A 2-tuple may be returned, consisting of a code object and a dict
161
of name/values to place into the target module.
163
Return None if the subfile was not found.
165
raise RuntimeError, "get_subfile not implemented"
168
class PackageArchive(PackageArchiveImporter):
169
"PackageArchiveImporter subclass that refers to a specific archive."
171
def __init__(self, modname, archive_pathname):
172
self.__modname = modname
173
self.__path = archive_pathname
175
def get_archive(self, modname):
176
if modname == self.__modname:
180
# get_subfile is passed the full pathname of the archive
183
######################################################################
185
# Emulate the standard directory-based import mechanism
187
class DirectoryImporter(imputil.Importer):
188
"Importer subclass to emulate the standard importer."
190
def __init__(self, dir):
193
def get_code(self, parent, modname, fqname):
195
dir = parent.__pkgdir__
199
# Return the module (and other info) if found in the specified
200
# directory. Otherwise, return None.
201
return _fs_import(dir, modname, fqname)
204
return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
205
self.__class__.__name__,
210
######################################################################
212
# Emulate the standard path-style import mechanism
214
class PathImporter(imputil.Importer):
215
def __init__(self, path=sys.path):
218
def get_code(self, parent, modname, fqname):
220
# we are looking for a module inside of a specific package
221
return _fs_import(parent.__pkgdir__, modname, fqname)
223
# scan sys.path, looking for the requested module
224
for dir in self.path:
225
if isinstance(dir, _StringType):
226
result = _fs_import(dir, modname, fqname)
233
######################################################################
236
"Debug/test function to create DirectoryImporters from sys.path."
237
imputil.ImportManager().install()
241
sys.path.insert(0, DirectoryImporter(d))
242
sys.path.insert(0, imputil.BuiltinImporter())
245
"Debug/test function for the revamped import system."
246
imputil.ImportManager().install()
247
sys.path.insert(0, PathImporter())
248
sys.path.insert(0, imputil.BuiltinImporter())