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())