blob: d442d9fa2281e9f55f47639b4afe104b9f07c1e5 [file] [log] [blame]
Greg Stein281b8d81999-11-07 12:54:45 +00001#
Greg Stein99a56212000-06-26 17:31:49 +00002# imputil.py: import utilities
Greg Stein281b8d81999-11-07 12:54:45 +00003#
Greg Stein99a56212000-06-26 17:31:49 +00004
5### docco needed here and in Docs/ ...
Greg Stein281b8d81999-11-07 12:54:45 +00006
Greg Stein281b8d81999-11-07 12:54:45 +00007# note: avoid importing non-builtin modules
Greg Stein3bb578c2000-02-18 13:04:10 +00008import imp ### not available in JPython?
Greg Stein281b8d81999-11-07 12:54:45 +00009import sys
10import strop
Greg Stein7ec28d21999-11-20 12:31:07 +000011import __builtin__
Greg Stein281b8d81999-11-07 12:54:45 +000012
13# for the DirectoryImporter
14import struct
15import marshal
16
Greg Steinf23aa1e2000-01-03 02:38:29 +000017_StringType = type('')
Greg Steind4f1d202000-02-18 12:03:40 +000018_ModuleType = type(sys) ### doesn't work in JPython...
Greg Steinf23aa1e2000-01-03 02:38:29 +000019
20class ImportManager:
Greg Steindd6eefb2000-07-18 09:09:48 +000021 "Manage the import process."
Greg Stein281b8d81999-11-07 12:54:45 +000022
Greg Steindd6eefb2000-07-18 09:09:48 +000023 def install(self, namespace=vars(__builtin__)):
24 "Install this ImportManager into the specified namespace."
Greg Steind4f1d202000-02-18 12:03:40 +000025
Greg Steindd6eefb2000-07-18 09:09:48 +000026 if isinstance(namespace, _ModuleType):
27 namespace = vars(namespace)
Greg Steind4f1d202000-02-18 12:03:40 +000028
Greg Steindd6eefb2000-07-18 09:09:48 +000029 ### Note that we have no notion of "uninstall" or "chaining"
Greg Stein3bb578c2000-02-18 13:04:10 +000030
Greg Steindd6eefb2000-07-18 09:09:48 +000031 namespace['__import__'] = self._import_hook
32 ### fix this
33 #namespace['reload'] = self._reload_hook
Greg Steinf23aa1e2000-01-03 02:38:29 +000034
Greg Steindd6eefb2000-07-18 09:09:48 +000035 def add_suffix(self, suffix, importFunc):
36 assert callable(importFunc)
37 self.fs_imp.add_suffix(suffix, importFunc)
Greg Stein281b8d81999-11-07 12:54:45 +000038
Greg Steindd6eefb2000-07-18 09:09:48 +000039 ######################################################################
40 #
41 # PRIVATE METHODS
42 #
Greg Stein3bb578c2000-02-18 13:04:10 +000043
Greg Steindd6eefb2000-07-18 09:09:48 +000044 clsFilesystemImporter = None
Greg Stein281b8d81999-11-07 12:54:45 +000045
Greg Steindd6eefb2000-07-18 09:09:48 +000046 def __init__(self, fs_imp=None):
47 # we're definitely going to be importing something in the future,
48 # so let's just load the OS-related facilities.
49 if not _os_stat:
50 _os_bootstrap()
Greg Stein3bb578c2000-02-18 13:04:10 +000051
Greg Steindd6eefb2000-07-18 09:09:48 +000052 # This is the Importer that we use for grabbing stuff from the
53 # filesystem. It defines one more method (import_from_dir) for our use.
54 if not fs_imp:
55 cls = self.clsFilesystemImporter or _FilesystemImporter
56 fs_imp = cls()
57 self.fs_imp = fs_imp
Greg Stein281b8d81999-11-07 12:54:45 +000058
Greg Steindd6eefb2000-07-18 09:09:48 +000059 # Initialize the set of suffixes that we recognize and import.
60 # The default will import dynamic-load modules first, followed by
61 # .py files (or a .py file's cached bytecode)
62 for desc in imp.get_suffixes():
63 if desc[2] == imp.C_EXTENSION:
64 self.add_suffix(desc[0],
65 DynLoadSuffixImporter(desc).import_file)
66 self.add_suffix('.py', py_suffix_importer)
Greg Steinf23aa1e2000-01-03 02:38:29 +000067
Greg Steindd6eefb2000-07-18 09:09:48 +000068 def _import_hook(self, fqname, globals=None, locals=None, fromlist=None):
69 """Python calls this hook to locate and import a module."""
Greg Stein63faa011999-11-20 11:22:37 +000070
Greg Steindd6eefb2000-07-18 09:09:48 +000071 parts = strop.split(fqname, '.')
Greg Stein281b8d81999-11-07 12:54:45 +000072
Greg Steindd6eefb2000-07-18 09:09:48 +000073 # determine the context of this import
74 parent = self._determine_import_context(globals)
Greg Stein281b8d81999-11-07 12:54:45 +000075
Greg Steindd6eefb2000-07-18 09:09:48 +000076 # if there is a parent, then its importer should manage this import
77 if parent:
78 module = parent.__importer__._do_import(parent, parts, fromlist)
79 if module:
80 return module
Greg Stein281b8d81999-11-07 12:54:45 +000081
Greg Steindd6eefb2000-07-18 09:09:48 +000082 # has the top module already been imported?
83 try:
84 top_module = sys.modules[parts[0]]
85 except KeyError:
86
87 # look for the topmost module
88 top_module = self._import_top_module(parts[0])
89 if not top_module:
90 # the topmost module wasn't found at all.
91 raise ImportError, 'No module named ' + fqname
92
93 # fast-path simple imports
94 if len(parts) == 1:
95 if not fromlist:
96 return top_module
97
98 if not top_module.__dict__.get('__ispkg__'):
99 # __ispkg__ isn't defined (the module was not imported by us),
100 # or it is zero.
101 #
102 # In the former case, there is no way that we could import
103 # sub-modules that occur in the fromlist (but we can't raise an
104 # error because it may just be names) because we don't know how
105 # to deal with packages that were imported by other systems.
106 #
107 # In the latter case (__ispkg__ == 0), there can't be any sub-
108 # modules present, so we can just return.
109 #
110 # In both cases, since len(parts) == 1, the top_module is also
111 # the "bottom" which is the defined return when a fromlist
112 # exists.
113 return top_module
114
115 importer = top_module.__dict__.get('__importer__')
116 if importer:
117 return importer._finish_import(top_module, parts[1:], fromlist)
118
119 # If the importer does not exist, then we have to bail. A missing
120 # importer means that something else imported the module, and we have
121 # no knowledge of how to get sub-modules out of the thing.
Greg Steinf23aa1e2000-01-03 02:38:29 +0000122 raise ImportError, 'No module named ' + fqname
Greg Steinf23aa1e2000-01-03 02:38:29 +0000123
Greg Steindd6eefb2000-07-18 09:09:48 +0000124 def _determine_import_context(self, globals):
125 """Returns the context in which a module should be imported.
Greg Steinf23aa1e2000-01-03 02:38:29 +0000126
Greg Steindd6eefb2000-07-18 09:09:48 +0000127 The context could be a loaded (package) module and the imported module
128 will be looked for within that package. The context could also be None,
129 meaning there is no context -- the module should be looked for as a
130 "top-level" module.
131 """
Greg Steinf23aa1e2000-01-03 02:38:29 +0000132
Greg Steindd6eefb2000-07-18 09:09:48 +0000133 if not globals or not globals.get('__importer__'):
134 # globals does not refer to one of our modules or packages. That
135 # implies there is no relative import context (as far as we are
136 # concerned), and it should just pick it off the standard path.
137 return None
Greg Steinf23aa1e2000-01-03 02:38:29 +0000138
Greg Steindd6eefb2000-07-18 09:09:48 +0000139 # The globals refer to a module or package of ours. It will define
140 # the context of the new import. Get the module/package fqname.
141 parent_fqname = globals['__name__']
Greg Steinf23aa1e2000-01-03 02:38:29 +0000142
Greg Steindd6eefb2000-07-18 09:09:48 +0000143 # if a package is performing the import, then return itself (imports
144 # refer to pkg contents)
145 if globals['__ispkg__']:
146 parent = sys.modules[parent_fqname]
147 assert globals is parent.__dict__
148 return parent
Greg Steinf23aa1e2000-01-03 02:38:29 +0000149
Greg Steindd6eefb2000-07-18 09:09:48 +0000150 i = strop.rfind(parent_fqname, '.')
Greg Steinf23aa1e2000-01-03 02:38:29 +0000151
Greg Steindd6eefb2000-07-18 09:09:48 +0000152 # a module outside of a package has no particular import context
153 if i == -1:
154 return None
Greg Steinf23aa1e2000-01-03 02:38:29 +0000155
Greg Steindd6eefb2000-07-18 09:09:48 +0000156 # if a module in a package is performing the import, then return the
157 # package (imports refer to siblings)
158 parent_fqname = parent_fqname[:i]
159 parent = sys.modules[parent_fqname]
160 assert parent.__name__ == parent_fqname
161 return parent
Greg Steinf23aa1e2000-01-03 02:38:29 +0000162
Greg Steindd6eefb2000-07-18 09:09:48 +0000163 def _import_top_module(self, name):
164 # scan sys.path looking for a location in the filesystem that contains
165 # the module, or an Importer object that can import the module.
166 for item in sys.path:
167 if isinstance(item, _StringType):
168 module = self.fs_imp.import_from_dir(item, name)
169 else:
170 module = item.import_top(name)
171 if module:
172 return module
173 return None
Greg Steinf23aa1e2000-01-03 02:38:29 +0000174
Greg Steindd6eefb2000-07-18 09:09:48 +0000175 def _reload_hook(self, module):
176 "Python calls this hook to reload a module."
Greg Steinf23aa1e2000-01-03 02:38:29 +0000177
Greg Steindd6eefb2000-07-18 09:09:48 +0000178 # reloading of a module may or may not be possible (depending on the
179 # importer), but at least we can validate that it's ours to reload
180 importer = module.__dict__.get('__importer__')
181 if not importer:
182 ### oops. now what...
183 pass
Greg Steinf23aa1e2000-01-03 02:38:29 +0000184
Greg Steindd6eefb2000-07-18 09:09:48 +0000185 # okay. it is using the imputil system, and we must delegate it, but
186 # we don't know what to do (yet)
187 ### we should blast the module dict and do another get_code(). need to
188 ### flesh this out and add proper docco...
189 raise SystemError, "reload not yet implemented"
Greg Steinf23aa1e2000-01-03 02:38:29 +0000190
191
192class Importer:
Greg Steindd6eefb2000-07-18 09:09:48 +0000193 "Base class for replacing standard import functions."
Greg Steinf23aa1e2000-01-03 02:38:29 +0000194
Greg Steindd6eefb2000-07-18 09:09:48 +0000195 def import_top(self, name):
196 "Import a top-level module."
197 return self._import_one(None, name, name)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000198
Greg Steindd6eefb2000-07-18 09:09:48 +0000199 ######################################################################
Greg Stein281b8d81999-11-07 12:54:45 +0000200 #
Greg Steindd6eefb2000-07-18 09:09:48 +0000201 # PRIVATE METHODS
Greg Stein281b8d81999-11-07 12:54:45 +0000202 #
Greg Steindd6eefb2000-07-18 09:09:48 +0000203 def _finish_import(self, top, parts, fromlist):
204 # if "a.b.c" was provided, then load the ".b.c" portion down from
205 # below the top-level module.
206 bottom = self._load_tail(top, parts)
Greg Stein281b8d81999-11-07 12:54:45 +0000207
Greg Steindd6eefb2000-07-18 09:09:48 +0000208 # if the form is "import a.b.c", then return "a"
209 if not fromlist:
210 # no fromlist: return the top of the import tree
211 return top
212
213 # the top module was imported by self.
214 #
215 # this means that the bottom module was also imported by self (just
216 # now, or in the past and we fetched it from sys.modules).
217 #
218 # since we imported/handled the bottom module, this means that we can
219 # also handle its fromlist (and reliably use __ispkg__).
220
221 # if the bottom node is a package, then (potentially) import some
222 # modules.
223 #
224 # note: if it is not a package, then "fromlist" refers to names in
225 # the bottom module rather than modules.
226 # note: for a mix of names and modules in the fromlist, we will
227 # import all modules and insert those into the namespace of
228 # the package module. Python will pick up all fromlist names
229 # from the bottom (package) module; some will be modules that
230 # we imported and stored in the namespace, others are expected
231 # to be present already.
232 if bottom.__ispkg__:
233 self._import_fromlist(bottom, fromlist)
234
235 # if the form is "from a.b import c, d" then return "b"
236 return bottom
237
238 def _import_one(self, parent, modname, fqname):
239 "Import a single module."
240
241 # has the module already been imported?
242 try:
243 return sys.modules[fqname]
244 except KeyError:
245 pass
246
247 # load the module's code, or fetch the module itself
248 result = self.get_code(parent, modname, fqname)
249 if result is None:
250 return None
251
252 module = self._process_result(result, fqname)
253
254 # insert the module into its parent
255 if parent:
256 setattr(parent, modname, module)
257 return module
258
259 def _process_result(self, (ispkg, code, values), fqname):
260 # did get_code() return an actual module? (rather than a code object)
261 is_module = isinstance(code, _ModuleType)
262
263 # use the returned module, or create a new one to exec code into
264 if is_module:
265 module = code
266 else:
267 module = imp.new_module(fqname)
268
269 ### record packages a bit differently??
270 module.__importer__ = self
271 module.__ispkg__ = ispkg
272
273 # insert additional values into the module (before executing the code)
274 module.__dict__.update(values)
275
276 # the module is almost ready... make it visible
277 sys.modules[fqname] = module
278
279 # execute the code within the module's namespace
280 if not is_module:
281 exec code in module.__dict__
282
283 return module
284
285 def _load_tail(self, m, parts):
286 """Import the rest of the modules, down from the top-level module.
287
288 Returns the last module in the dotted list of modules.
289 """
290 for part in parts:
291 fqname = "%s.%s" % (m.__name__, part)
292 m = self._import_one(m, part, fqname)
293 if not m:
294 raise ImportError, "No module named " + fqname
295 return m
296
297 def _import_fromlist(self, package, fromlist):
298 'Import any sub-modules in the "from" list.'
299
300 # if '*' is present in the fromlist, then look for the '__all__'
301 # variable to find additional items (modules) to import.
302 if '*' in fromlist:
303 fromlist = list(fromlist) + \
304 list(package.__dict__.get('__all__', []))
305
306 for sub in fromlist:
307 # if the name is already present, then don't try to import it (it
308 # might not be a module!).
309 if sub != '*' and not hasattr(package, sub):
310 subname = "%s.%s" % (package.__name__, sub)
311 submod = self._import_one(package, sub, subname)
312 if not submod:
313 raise ImportError, "cannot import name " + subname
314
315 def _do_import(self, parent, parts, fromlist):
316 """Attempt to import the module relative to parent.
317
318 This method is used when the import context specifies that <self>
319 imported the parent module.
320 """
321 top_name = parts[0]
322 top_fqname = parent.__name__ + '.' + top_name
323 top_module = self._import_one(parent, top_name, top_fqname)
324 if not top_module:
325 # this importer and parent could not find the module (relatively)
326 return None
327
328 return self._finish_import(top_module, parts[1:], fromlist)
329
330 ######################################################################
Greg Stein281b8d81999-11-07 12:54:45 +0000331 #
Greg Steindd6eefb2000-07-18 09:09:48 +0000332 # METHODS TO OVERRIDE
333 #
334 def get_code(self, parent, modname, fqname):
335 """Find and retrieve the code for the given module.
Greg Stein281b8d81999-11-07 12:54:45 +0000336
Greg Steindd6eefb2000-07-18 09:09:48 +0000337 parent specifies a parent module to define a context for importing. It
338 may be None, indicating no particular context for the search.
Greg Stein281b8d81999-11-07 12:54:45 +0000339
Greg Steindd6eefb2000-07-18 09:09:48 +0000340 modname specifies a single module (not dotted) within the parent.
Greg Stein281b8d81999-11-07 12:54:45 +0000341
Greg Steindd6eefb2000-07-18 09:09:48 +0000342 fqname specifies the fully-qualified module name. This is a
343 (potentially) dotted name from the "root" of the module namespace
344 down to the modname.
345 If there is no parent, then modname==fqname.
Greg Stein281b8d81999-11-07 12:54:45 +0000346
Greg Steindd6eefb2000-07-18 09:09:48 +0000347 This method should return None, or a 3-tuple.
Greg Stein281b8d81999-11-07 12:54:45 +0000348
Greg Steindd6eefb2000-07-18 09:09:48 +0000349 * If the module was not found, then None should be returned.
Greg Stein281b8d81999-11-07 12:54:45 +0000350
Greg Steindd6eefb2000-07-18 09:09:48 +0000351 * The first item of the 2- or 3-tuple should be the integer 0 or 1,
352 specifying whether the module that was found is a package or not.
Greg Stein281b8d81999-11-07 12:54:45 +0000353
Greg Steindd6eefb2000-07-18 09:09:48 +0000354 * The second item is the code object for the module (it will be
355 executed within the new module's namespace). This item can also
356 be a fully-loaded module object (e.g. loaded from a shared lib).
Greg Steinf23aa1e2000-01-03 02:38:29 +0000357
Greg Steindd6eefb2000-07-18 09:09:48 +0000358 * The third item is a dictionary of name/value pairs that will be
359 inserted into new module before the code object is executed. This
360 is provided in case the module's code expects certain values (such
361 as where the module was found). When the second item is a module
362 object, then these names/values will be inserted *after* the module
363 has been loaded/initialized.
364 """
365 raise RuntimeError, "get_code not implemented"
Greg Stein281b8d81999-11-07 12:54:45 +0000366
367
368######################################################################
369#
Greg Stein63faa011999-11-20 11:22:37 +0000370# Some handy stuff for the Importers
371#
372
Greg Steind4f1d202000-02-18 12:03:40 +0000373# byte-compiled file suffix character
Greg Stein63faa011999-11-20 11:22:37 +0000374_suffix_char = __debug__ and 'c' or 'o'
375
376# byte-compiled file suffix
377_suffix = '.py' + _suffix_char
378
Greg Stein63faa011999-11-20 11:22:37 +0000379def _compile(pathname, timestamp):
Greg Steindd6eefb2000-07-18 09:09:48 +0000380 """Compile (and cache) a Python source file.
Greg Stein63faa011999-11-20 11:22:37 +0000381
Greg Steindd6eefb2000-07-18 09:09:48 +0000382 The file specified by <pathname> is compiled to a code object and
383 returned.
Greg Stein63faa011999-11-20 11:22:37 +0000384
Greg Steindd6eefb2000-07-18 09:09:48 +0000385 Presuming the appropriate privileges exist, the bytecodes will be
386 saved back to the filesystem for future imports. The source file's
387 modification timestamp must be provided as a Long value.
388 """
389 codestring = open(pathname, 'r').read()
390 if codestring and codestring[-1] != '\n':
391 codestring = codestring + '\n'
392 code = __builtin__.compile(codestring, pathname, 'exec')
Greg Stein63faa011999-11-20 11:22:37 +0000393
Greg Steindd6eefb2000-07-18 09:09:48 +0000394 # try to cache the compiled code
395 try:
396 f = open(pathname + _suffix_char, 'wb')
397 except IOError:
398 pass
399 else:
400 f.write('\0\0\0\0')
401 f.write(struct.pack('<I', timestamp))
402 marshal.dump(code, f)
403 f.flush()
404 f.seek(0, 0)
405 f.write(imp.get_magic())
406 f.close()
Greg Stein63faa011999-11-20 11:22:37 +0000407
Greg Steindd6eefb2000-07-18 09:09:48 +0000408 return code
Greg Stein63faa011999-11-20 11:22:37 +0000409
410_os_stat = _os_path_join = None
411def _os_bootstrap():
Greg Steindd6eefb2000-07-18 09:09:48 +0000412 "Set up 'os' module replacement functions for use during import bootstrap."
Greg Stein63faa011999-11-20 11:22:37 +0000413
Greg Steindd6eefb2000-07-18 09:09:48 +0000414 names = sys.builtin_module_names
Greg Stein63faa011999-11-20 11:22:37 +0000415
Greg Steindd6eefb2000-07-18 09:09:48 +0000416 join = None
417 if 'posix' in names:
418 sep = '/'
419 from posix import stat
420 elif 'nt' in names:
421 sep = '\\'
422 from nt import stat
423 elif 'dos' in names:
424 sep = '\\'
425 from dos import stat
426 elif 'os2' in names:
427 sep = '\\'
428 from os2 import stat
429 elif 'mac' in names:
430 from mac import stat
431 def join(a, b):
432 if a == '':
433 return b
434 path = s
435 if ':' not in a:
436 a = ':' + a
437 if a[-1:] <> ':':
438 a = a + ':'
439 return a + b
440 else:
441 raise ImportError, 'no os specific module found'
Greg Stein63faa011999-11-20 11:22:37 +0000442
Greg Steindd6eefb2000-07-18 09:09:48 +0000443 if join is None:
444 def join(a, b, sep=sep):
445 if a == '':
446 return b
447 lastchar = a[-1:]
448 if lastchar == '/' or lastchar == sep:
449 return a + b
450 return a + sep + b
Greg Stein63faa011999-11-20 11:22:37 +0000451
Greg Steindd6eefb2000-07-18 09:09:48 +0000452 global _os_stat
453 _os_stat = stat
454
455 global _os_path_join
456 _os_path_join = join
Greg Stein63faa011999-11-20 11:22:37 +0000457
458def _os_path_isdir(pathname):
Greg Steindd6eefb2000-07-18 09:09:48 +0000459 "Local replacement for os.path.isdir()."
460 try:
461 s = _os_stat(pathname)
462 except OSError:
463 return None
464 return (s[0] & 0170000) == 0040000
Greg Stein63faa011999-11-20 11:22:37 +0000465
466def _timestamp(pathname):
Greg Steindd6eefb2000-07-18 09:09:48 +0000467 "Return the file modification time as a Long."
468 try:
469 s = _os_stat(pathname)
470 except OSError:
471 return None
472 return long(s[8])
Greg Stein63faa011999-11-20 11:22:37 +0000473
Greg Stein63faa011999-11-20 11:22:37 +0000474
475######################################################################
476#
477# Emulate the import mechanism for builtin and frozen modules
478#
479class BuiltinImporter(Importer):
Greg Steindd6eefb2000-07-18 09:09:48 +0000480 def get_code(self, parent, modname, fqname):
481 if parent:
482 # these modules definitely do not occur within a package context
483 return None
Greg Stein63faa011999-11-20 11:22:37 +0000484
Greg Steindd6eefb2000-07-18 09:09:48 +0000485 # look for the module
486 if imp.is_builtin(modname):
487 type = imp.C_BUILTIN
488 elif imp.is_frozen(modname):
489 type = imp.PY_FROZEN
490 else:
491 # not found
492 return None
Greg Stein63faa011999-11-20 11:22:37 +0000493
Greg Steindd6eefb2000-07-18 09:09:48 +0000494 # got it. now load and return it.
495 module = imp.load_module(modname, None, modname, ('', '', type))
496 return 0, module, { }
Greg Stein63faa011999-11-20 11:22:37 +0000497
498
499######################################################################
Greg Steinf23aa1e2000-01-03 02:38:29 +0000500#
501# Internal importer used for importing from the filesystem
502#
503class _FilesystemImporter(Importer):
Greg Steindd6eefb2000-07-18 09:09:48 +0000504 def __init__(self):
505 self.suffixes = [ ]
Greg Stein3bb578c2000-02-18 13:04:10 +0000506
Greg Steindd6eefb2000-07-18 09:09:48 +0000507 def add_suffix(self, suffix, importFunc):
508 assert callable(importFunc)
509 self.suffixes.append((suffix, importFunc))
Greg Steinf23aa1e2000-01-03 02:38:29 +0000510
Greg Steindd6eefb2000-07-18 09:09:48 +0000511 def import_from_dir(self, dir, fqname):
512 result = self._import_pathname(_os_path_join(dir, fqname), fqname)
513 if result:
514 return self._process_result(result, fqname)
515 return None
Greg Steinf23aa1e2000-01-03 02:38:29 +0000516
Greg Steindd6eefb2000-07-18 09:09:48 +0000517 def get_code(self, parent, modname, fqname):
518 # This importer is never used with an empty parent. Its existence is
519 # private to the ImportManager. The ImportManager uses the
520 # import_from_dir() method to import top-level modules/packages.
521 # This method is only used when we look for a module within a package.
522 assert parent
Greg Steinf23aa1e2000-01-03 02:38:29 +0000523
Greg Steindd6eefb2000-07-18 09:09:48 +0000524 return self._import_pathname(_os_path_join(parent.__pkgdir__, modname),
Greg Steinf23aa1e2000-01-03 02:38:29 +0000525 fqname)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000526
Greg Steindd6eefb2000-07-18 09:09:48 +0000527 def _import_pathname(self, pathname, fqname):
528 if _os_path_isdir(pathname):
529 result = self._import_pathname(_os_path_join(pathname, '__init__'),
530 fqname)
531 if result:
532 values = result[2]
533 values['__pkgdir__'] = pathname
534 values['__path__'] = [ pathname ]
535 return 1, result[1], values
536 return None
537
538 for suffix, importFunc in self.suffixes:
539 filename = pathname + suffix
540 try:
541 finfo = _os_stat(filename)
542 except OSError:
543 pass
544 else:
545 return importFunc(filename, finfo, fqname)
546 return None
Greg Steinf23aa1e2000-01-03 02:38:29 +0000547
548######################################################################
549#
550# SUFFIX-BASED IMPORTERS
551#
552
Greg Stein3bb578c2000-02-18 13:04:10 +0000553def py_suffix_importer(filename, finfo, fqname):
Greg Steindd6eefb2000-07-18 09:09:48 +0000554 file = filename[:-3] + _suffix
555 t_py = long(finfo[8])
556 t_pyc = _timestamp(file)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000557
Greg Steindd6eefb2000-07-18 09:09:48 +0000558 code = None
559 if t_pyc is not None and t_pyc >= t_py:
560 f = open(file, 'rb')
561 if f.read(4) == imp.get_magic():
562 t = struct.unpack('<I', f.read(4))[0]
563 if t == t_py:
564 code = marshal.load(f)
565 f.close()
566 if code is None:
567 file = filename
568 code = _compile(file, t_py)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000569
Greg Steindd6eefb2000-07-18 09:09:48 +0000570 return 0, code, { '__file__' : file }
Greg Steinf23aa1e2000-01-03 02:38:29 +0000571
Greg Stein3bb578c2000-02-18 13:04:10 +0000572class DynLoadSuffixImporter:
Greg Steindd6eefb2000-07-18 09:09:48 +0000573 def __init__(self, desc):
574 self.desc = desc
Greg Steinf23aa1e2000-01-03 02:38:29 +0000575
Greg Steindd6eefb2000-07-18 09:09:48 +0000576 def import_file(self, filename, finfo, fqname):
577 fp = open(filename, self.desc[1])
578 module = imp.load_module(fqname, fp, filename, self.desc)
579 module.__file__ = filename
580 return 0, module, { }
Greg Steinf23aa1e2000-01-03 02:38:29 +0000581
582
583######################################################################
Greg Stein63faa011999-11-20 11:22:37 +0000584
Greg Stein63faa011999-11-20 11:22:37 +0000585def _print_importers():
Greg Steindd6eefb2000-07-18 09:09:48 +0000586 items = sys.modules.items()
587 items.sort()
588 for name, module in items:
589 if module:
590 print name, module.__dict__.get('__importer__', '-- no importer')
591 else:
592 print name, '-- non-existent module'
Greg Stein63faa011999-11-20 11:22:37 +0000593
Greg Steinf23aa1e2000-01-03 02:38:29 +0000594def _test_revamp():
Greg Steindd6eefb2000-07-18 09:09:48 +0000595 ImportManager().install()
596 sys.path.insert(0, BuiltinImporter())
Greg Steinf23aa1e2000-01-03 02:38:29 +0000597
Greg Stein281b8d81999-11-07 12:54:45 +0000598######################################################################
Greg Stein42b9bc72000-02-19 13:36:23 +0000599
600#
601# TODO
602#
603# from Finn Bock:
604# remove use of "strop" -- not available in JPython
605# type(sys) is not a module in JPython. what to use instead?
606# imp.C_EXTENSION is not in JPython. same for get_suffixes and new_module
607#
608# given foo.py of:
609# import sys
610# sys.modules['foo'] = sys
611#
612# ---- standard import mechanism
613# >>> import foo
614# >>> foo
615# <module 'sys' (built-in)>
616#
617# ---- revamped import mechanism
618# >>> import imputil
619# >>> imputil._test_revamp()
620# >>> import foo
621# >>> foo
622# <module 'foo' from 'foo.py'>
623#
624#
625# from MAL:
626# should BuiltinImporter exist in sys.path or hard-wired in ImportManager?
627# need __path__ processing
628# performance
629# move chaining to a subclass [gjs: it's been nuked]
630# avoid strop
631# deinstall should be possible
632# query mechanism needed: is a specific Importer installed?
633# py/pyc/pyo piping hooks to filter/process these files
634# wish list:
635# distutils importer hooked to list of standard Internet repositories
636# module->file location mapper to speed FS-based imports
637# relative imports
638# keep chaining so that it can play nice with other import hooks
639#
640# from Gordon:
641# push MAL's mapper into sys.path[0] as a cache (hard-coded for apps)
642#
643# from Guido:
644# need to change sys.* references for rexec environs
645# need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy
646# watch out for sys.modules[...] == None
647# flag to force absolute imports? (speeds _determine_import_context and
648# checking for a relative module)
649# insert names of archives into sys.path (see quote below)
650# note: reload does NOT blast module dict
651# shift import mechanisms and policies around; provide for hooks, overrides
652# (see quote below)
653# add get_source stuff
654# get_topcode and get_subcode
655# CRLF handling in _compile
656# race condition in _compile
657# refactoring of os.py to deal with _os_bootstrap problem
658# any special handling to do for importing a module with a SyntaxError?
659# (e.g. clean up the traceback)
660# implement "domain" for path-type functionality using pkg namespace
661# (rather than FS-names like __path__)
662# don't use the word "private"... maybe "internal"
663#
664#
665# Guido's comments on sys.path caching:
666#
667# We could cache this in a dictionary: the ImportManager can have a
668# cache dict mapping pathnames to importer objects, and a separate
669# method for coming up with an importer given a pathname that's not yet
670# in the cache. The method should do a stat and/or look at the
671# extension to decide which importer class to use; you can register new
672# importer classes by registering a suffix or a Boolean function, plus a
673# class. If you register a new importer class, the cache is zapped.
674# The cache is independent from sys.path (but maintained per
675# ImportManager instance) so that rearrangements of sys.path do the
676# right thing. If a path is dropped from sys.path the corresponding
677# cache entry is simply no longer used.
678#
679# My/Guido's comments on factoring ImportManager and Importer:
680#
681# > However, we still have a tension occurring here:
682# >
683# > 1) implementing policy in ImportManager assists in single-point policy
684# > changes for app/rexec situations
685# > 2) implementing policy in Importer assists in package-private policy
686# > changes for normal, operating conditions
687# >
688# > I'll see if I can sort out a way to do this. Maybe the Importer class will
689# > implement the methods (which can be overridden to change policy) by
690# > delegating to ImportManager.
691#
692# Maybe also think about what kind of policies an Importer would be
693# likely to want to change. I have a feeling that a lot of the code
694# there is actually not so much policy but a *necessity* to get things
695# working given the calling conventions for the __import__ hook: whether
696# to return the head or tail of a dotted name, or when to do the "finish
697# fromlist" stuff.
698#