blob: b2a643ad21785850b2c83fc7a2db524dc0d1980a [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:
21 "Manage the import process."
Greg Stein281b8d81999-11-07 12:54:45 +000022
Greg Steind4f1d202000-02-18 12:03:40 +000023 def install(self, namespace=vars(__builtin__)):
24 "Install this ImportManager into the specified namespace."
25
26 if isinstance(namespace, _ModuleType):
27 namespace = vars(namespace)
28
29 ### Note that we have no notion of "uninstall" or "chaining"
Greg Stein3bb578c2000-02-18 13:04:10 +000030
Greg Steind4f1d202000-02-18 12:03:40 +000031 namespace['__import__'] = self._import_hook
Greg Steinf23aa1e2000-01-03 02:38:29 +000032 ### fix this
Greg Steind4f1d202000-02-18 12:03:40 +000033 #namespace['reload'] = self._reload_hook
Greg Steinf23aa1e2000-01-03 02:38:29 +000034
Greg Stein3bb578c2000-02-18 13:04:10 +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
39 ######################################################################
40 #
41 # PRIVATE METHODS
42 #
Greg Stein3bb578c2000-02-18 13:04:10 +000043
44 clsFilesystemImporter = None
45
46 def __init__(self, fs_imp=None):
Greg Steinf23aa1e2000-01-03 02:38:29 +000047 # 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 Stein281b8d81999-11-07 12:54:45 +000051
Greg Stein3bb578c2000-02-18 13:04:10 +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
58
Greg Steinf23aa1e2000-01-03 02:38:29 +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)
Greg Steinf23aa1e2000-01-03 02:38:29 +000062 for desc in imp.get_suffixes():
63 if desc[2] == imp.C_EXTENSION:
Greg Stein3bb578c2000-02-18 13:04:10 +000064 self.add_suffix(desc[0], DynLoadSuffixImporter(desc).import_file)
65 self.add_suffix('.py', py_suffix_importer)
Greg Stein281b8d81999-11-07 12:54:45 +000066
Greg Steinf23aa1e2000-01-03 02:38:29 +000067 def _import_hook(self, fqname, globals=None, locals=None, fromlist=None):
68 """Python calls this hook to locate and import a module."""
69
70 parts = strop.split(fqname, '.')
Greg Stein63faa011999-11-20 11:22:37 +000071
Greg Stein281b8d81999-11-07 12:54:45 +000072 # determine the context of this import
73 parent = self._determine_import_context(globals)
74
Greg Steinf23aa1e2000-01-03 02:38:29 +000075 # if there is a parent, then its importer should manage this import
76 if parent:
77 module = parent.__importer__._do_import(parent, parts, fromlist)
78 if module:
79 return module
Greg Stein281b8d81999-11-07 12:54:45 +000080
Greg Steinf23aa1e2000-01-03 02:38:29 +000081 # has the top module already been imported?
82 try:
83 top_module = sys.modules[parts[0]]
84 except KeyError:
Greg Stein281b8d81999-11-07 12:54:45 +000085
Greg Steinf23aa1e2000-01-03 02:38:29 +000086 # look for the topmost module
87 top_module = self._import_top_module(parts[0])
88 if not top_module:
89 # the topmost module wasn't found at all.
90 raise ImportError, 'No module named ' + fqname
Greg Steinf23aa1e2000-01-03 02:38:29 +000091
92 # fast-path simple imports
93 if len(parts) == 1:
94 if not fromlist:
95 return top_module
96
97 if not top_module.__dict__.get('__ispkg__'):
98 # __ispkg__ isn't defined (the module was not imported by us), or
99 # it is zero.
100 #
101 # In the former case, there is no way that we could import
102 # sub-modules that occur in the fromlist (but we can't raise an
103 # error because it may just be names) because we don't know how
104 # to deal with packages that were imported by other systems.
105 #
106 # In the latter case (__ispkg__ == 0), there can't be any sub-
107 # modules present, so we can just return.
108 #
109 # In both cases, since len(parts) == 1, the top_module is also
110 # the "bottom" which is the defined return when a fromlist exists.
111 return top_module
112
113 importer = top_module.__dict__.get('__importer__')
114 if importer:
115 return importer._finish_import(top_module, parts[1:], fromlist)
116
117 # If the importer does not exist, then we have to bail. A missing importer
118 # means that something else imported the module, and we have no knowledge
119 # of how to get sub-modules out of the thing.
120 raise ImportError, 'No module named ' + fqname
Greg Steinf23aa1e2000-01-03 02:38:29 +0000121
122 def _determine_import_context(self, globals):
123 """Returns the context in which a module should be imported.
124
125 The context could be a loaded (package) module and the imported module
126 will be looked for within that package. The context could also be None,
127 meaning there is no context -- the module should be looked for as a
128 "top-level" module.
129 """
130
131 if not globals or not globals.get('__importer__'):
132 # globals does not refer to one of our modules or packages. That
133 # implies there is no relative import context (as far as we are
134 # concerned), and it should just pick it off the standard path.
135 return None
136
137 # The globals refer to a module or package of ours. It will define
138 # the context of the new import. Get the module/package fqname.
139 parent_fqname = globals['__name__']
140
141 # if a package is performing the import, then return itself (imports
142 # refer to pkg contents)
143 if globals['__ispkg__']:
144 parent = sys.modules[parent_fqname]
145 assert globals is parent.__dict__
146 return parent
147
148 i = strop.rfind(parent_fqname, '.')
149
150 # a module outside of a package has no particular import context
151 if i == -1:
152 return None
153
154 # if a module in a package is performing the import, then return the
155 # package (imports refer to siblings)
156 parent_fqname = parent_fqname[:i]
157 parent = sys.modules[parent_fqname]
158 assert parent.__name__ == parent_fqname
159 return parent
160
161 def _import_top_module(self, name):
162 # scan sys.path looking for a location in the filesystem that contains
163 # the module, or an Importer object that can import the module.
164 for item in sys.path:
Greg Steind4f1d202000-02-18 12:03:40 +0000165 if isinstance(item, _StringType):
Greg Steinf23aa1e2000-01-03 02:38:29 +0000166 module = self.fs_imp.import_from_dir(item, name)
167 else:
168 module = item.import_top(name)
169 if module:
170 return module
171 return None
172
173 def _reload_hook(self, module):
174 "Python calls this hook to reload a module."
175
176 # reloading of a module may or may not be possible (depending on the
177 # importer), but at least we can validate that it's ours to reload
178 importer = module.__dict__.get('__importer__')
179 if not importer:
Greg Steind4f1d202000-02-18 12:03:40 +0000180 ### oops. now what...
181 pass
Greg Steinf23aa1e2000-01-03 02:38:29 +0000182
183 # okay. it is using the imputil system, and we must delegate it, but
184 # we don't know what to do (yet)
185 ### we should blast the module dict and do another get_code(). need to
186 ### flesh this out and add proper docco...
187 raise SystemError, "reload not yet implemented"
188
189
190class Importer:
191 "Base class for replacing standard import functions."
192
Greg Steinf23aa1e2000-01-03 02:38:29 +0000193 def import_top(self, name):
194 "Import a top-level module."
195 return self._import_one(None, name, name)
196
197 ######################################################################
198 #
199 # PRIVATE METHODS
200 #
201 def _finish_import(self, top, parts, fromlist):
Greg Stein281b8d81999-11-07 12:54:45 +0000202 # if "a.b.c" was provided, then load the ".b.c" portion down from
203 # below the top-level module.
Greg Steinf23aa1e2000-01-03 02:38:29 +0000204 bottom = self._load_tail(top, parts)
Greg Stein281b8d81999-11-07 12:54:45 +0000205
206 # if the form is "import a.b.c", then return "a"
207 if not fromlist:
208 # no fromlist: return the top of the import tree
209 return top
210
Greg Steinf23aa1e2000-01-03 02:38:29 +0000211 # the top module was imported by self.
Greg Stein281b8d81999-11-07 12:54:45 +0000212 #
Greg Steinf23aa1e2000-01-03 02:38:29 +0000213 # this means that the bottom module was also imported by self (just
214 # now, or in the past and we fetched it from sys.modules).
Greg Stein281b8d81999-11-07 12:54:45 +0000215 #
216 # since we imported/handled the bottom module, this means that we can
Greg Steinf23aa1e2000-01-03 02:38:29 +0000217 # also handle its fromlist (and reliably use __ispkg__).
Greg Stein281b8d81999-11-07 12:54:45 +0000218
219 # if the bottom node is a package, then (potentially) import some modules.
220 #
221 # note: if it is not a package, then "fromlist" refers to names in
222 # the bottom module rather than modules.
223 # note: for a mix of names and modules in the fromlist, we will
224 # import all modules and insert those into the namespace of
225 # the package module. Python will pick up all fromlist names
226 # from the bottom (package) module; some will be modules that
227 # we imported and stored in the namespace, others are expected
228 # to be present already.
Greg Steinf23aa1e2000-01-03 02:38:29 +0000229 if bottom.__ispkg__:
Greg Stein281b8d81999-11-07 12:54:45 +0000230 self._import_fromlist(bottom, fromlist)
231
232 # if the form is "from a.b import c, d" then return "b"
233 return bottom
234
Greg Stein281b8d81999-11-07 12:54:45 +0000235 def _import_one(self, parent, modname, fqname):
236 "Import a single module."
237
238 # has the module already been imported?
239 try:
240 return sys.modules[fqname]
241 except KeyError:
242 pass
243
244 # load the module's code, or fetch the module itself
245 result = self.get_code(parent, modname, fqname)
246 if result is None:
247 return None
248
Greg Steinf23aa1e2000-01-03 02:38:29 +0000249 module = self._process_result(result, fqname)
Greg Stein281b8d81999-11-07 12:54:45 +0000250
251 # insert the module into its parent
252 if parent:
253 setattr(parent, modname, module)
254 return module
255
Greg Steinf23aa1e2000-01-03 02:38:29 +0000256 def _process_result(self, (ispkg, code, values), fqname):
257 # did get_code() return an actual module? (rather than a code object)
Greg Steind4f1d202000-02-18 12:03:40 +0000258 is_module = isinstance(code, _ModuleType)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000259
260 # use the returned module, or create a new one to exec code into
261 if is_module:
262 module = code
263 else:
264 module = imp.new_module(fqname)
265
266 ### record packages a bit differently??
267 module.__importer__ = self
268 module.__ispkg__ = ispkg
269
270 # insert additional values into the module (before executing the code)
271 module.__dict__.update(values)
272
273 # the module is almost ready... make it visible
274 sys.modules[fqname] = module
275
276 # execute the code within the module's namespace
277 if not is_module:
278 exec code in module.__dict__
279
280 return module
281
282 def _load_tail(self, m, parts):
Greg Stein281b8d81999-11-07 12:54:45 +0000283 """Import the rest of the modules, down from the top-level module.
284
285 Returns the last module in the dotted list of modules.
286 """
Greg Steinf23aa1e2000-01-03 02:38:29 +0000287 for part in parts:
288 fqname = "%s.%s" % (m.__name__, part)
289 m = self._import_one(m, part, fqname)
290 if not m:
291 raise ImportError, "No module named " + fqname
Greg Stein281b8d81999-11-07 12:54:45 +0000292 return m
293
294 def _import_fromlist(self, package, fromlist):
295 'Import any sub-modules in the "from" list.'
296
297 # if '*' is present in the fromlist, then look for the '__all__' variable
298 # to find additional items (modules) to import.
299 if '*' in fromlist:
300 fromlist = list(fromlist) + list(package.__dict__.get('__all__', []))
301
302 for sub in fromlist:
303 # if the name is already present, then don't try to import it (it
304 # might not be a module!).
305 if sub != '*' and not hasattr(package, sub):
306 subname = "%s.%s" % (package.__name__, sub)
307 submod = self._import_one(package, sub, subname)
308 if not submod:
309 raise ImportError, "cannot import name " + subname
310
Greg Steinf23aa1e2000-01-03 02:38:29 +0000311 def _do_import(self, parent, parts, fromlist):
312 """Attempt to import the module relative to parent.
Greg Stein281b8d81999-11-07 12:54:45 +0000313
Greg Steinf23aa1e2000-01-03 02:38:29 +0000314 This method is used when the import context specifies that <self>
315 imported the parent module.
Greg Stein281b8d81999-11-07 12:54:45 +0000316 """
Greg Steinf23aa1e2000-01-03 02:38:29 +0000317 top_name = parts[0]
318 top_fqname = parent.__name__ + '.' + top_name
319 top_module = self._import_one(parent, top_name, top_fqname)
320 if not top_module:
321 # this importer and parent could not find the module (relatively)
322 return None
323
324 return self._finish_import(top_module, parts[1:], fromlist)
Greg Stein281b8d81999-11-07 12:54:45 +0000325
326 ######################################################################
327 #
328 # METHODS TO OVERRIDE
329 #
330 def get_code(self, parent, modname, fqname):
331 """Find and retrieve the code for the given module.
332
333 parent specifies a parent module to define a context for importing. It
334 may be None, indicating no particular context for the search.
335
336 modname specifies a single module (not dotted) within the parent.
337
338 fqname specifies the fully-qualified module name. This is a (potentially)
339 dotted name from the "root" of the module namespace down to the modname.
340 If there is no parent, then modname==fqname.
341
Greg Steinf23aa1e2000-01-03 02:38:29 +0000342 This method should return None, or a 3-tuple.
Greg Stein281b8d81999-11-07 12:54:45 +0000343
344 * If the module was not found, then None should be returned.
345
346 * The first item of the 2- or 3-tuple should be the integer 0 or 1,
347 specifying whether the module that was found is a package or not.
348
349 * The second item is the code object for the module (it will be
350 executed within the new module's namespace). This item can also
351 be a fully-loaded module object (e.g. loaded from a shared lib).
352
Greg Steinf23aa1e2000-01-03 02:38:29 +0000353 * The third item is a dictionary of name/value pairs that will be
354 inserted into new module before the code object is executed. This
355 is provided in case the module's code expects certain values (such
Greg Stein281b8d81999-11-07 12:54:45 +0000356 as where the module was found). When the second item is a module
357 object, then these names/values will be inserted *after* the module
358 has been loaded/initialized.
359 """
360 raise RuntimeError, "get_code not implemented"
361
362
363######################################################################
364#
Greg Stein63faa011999-11-20 11:22:37 +0000365# Some handy stuff for the Importers
366#
367
Greg Steind4f1d202000-02-18 12:03:40 +0000368# byte-compiled file suffix character
Greg Stein63faa011999-11-20 11:22:37 +0000369_suffix_char = __debug__ and 'c' or 'o'
370
371# byte-compiled file suffix
372_suffix = '.py' + _suffix_char
373
Greg Stein63faa011999-11-20 11:22:37 +0000374def _compile(pathname, timestamp):
375 """Compile (and cache) a Python source file.
376
377 The file specified by <pathname> is compiled to a code object and
378 returned.
379
380 Presuming the appropriate privileges exist, the bytecodes will be
381 saved back to the filesystem for future imports. The source file's
382 modification timestamp must be provided as a Long value.
383 """
384 codestring = open(pathname, 'r').read()
385 if codestring and codestring[-1] != '\n':
386 codestring = codestring + '\n'
387 code = __builtin__.compile(codestring, pathname, 'exec')
388
389 # try to cache the compiled code
390 try:
391 f = open(pathname + _suffix_char, 'wb')
392 except IOError:
393 pass
394 else:
395 f.write('\0\0\0\0')
396 f.write(struct.pack('<I', timestamp))
397 marshal.dump(code, f)
398 f.flush()
399 f.seek(0, 0)
400 f.write(imp.get_magic())
401 f.close()
402
403 return code
404
405_os_stat = _os_path_join = None
406def _os_bootstrap():
407 "Set up 'os' module replacement functions for use during import bootstrap."
408
409 names = sys.builtin_module_names
410
411 join = None
412 if 'posix' in names:
413 sep = '/'
414 from posix import stat
415 elif 'nt' in names:
416 sep = '\\'
417 from nt import stat
418 elif 'dos' in names:
419 sep = '\\'
420 from dos import stat
421 elif 'os2' in names:
422 sep = '\\'
423 from os2 import stat
424 elif 'mac' in names:
425 from mac import stat
426 def join(a, b):
427 if a == '':
428 return b
429 path = s
430 if ':' not in a:
431 a = ':' + a
432 if a[-1:] <> ':':
433 a = a + ':'
434 return a + b
435 else:
436 raise ImportError, 'no os specific module found'
437
438 if join is None:
439 def join(a, b, sep=sep):
440 if a == '':
441 return b
442 lastchar = a[-1:]
443 if lastchar == '/' or lastchar == sep:
444 return a + b
445 return a + sep + b
446
447 global _os_stat
448 _os_stat = stat
449
450 global _os_path_join
451 _os_path_join = join
452
453def _os_path_isdir(pathname):
454 "Local replacement for os.path.isdir()."
455 try:
456 s = _os_stat(pathname)
457 except OSError:
458 return None
459 return (s[0] & 0170000) == 0040000
460
461def _timestamp(pathname):
462 "Return the file modification time as a Long."
463 try:
464 s = _os_stat(pathname)
465 except OSError:
466 return None
467 return long(s[8])
468
Greg Stein63faa011999-11-20 11:22:37 +0000469
470######################################################################
471#
472# Emulate the import mechanism for builtin and frozen modules
473#
474class BuiltinImporter(Importer):
475 def get_code(self, parent, modname, fqname):
476 if parent:
477 # these modules definitely do not occur within a package context
478 return None
479
480 # look for the module
481 if imp.is_builtin(modname):
482 type = imp.C_BUILTIN
483 elif imp.is_frozen(modname):
484 type = imp.PY_FROZEN
485 else:
486 # not found
487 return None
488
489 # got it. now load and return it.
490 module = imp.load_module(modname, None, modname, ('', '', type))
491 return 0, module, { }
492
493
494######################################################################
Greg Steinf23aa1e2000-01-03 02:38:29 +0000495#
496# Internal importer used for importing from the filesystem
497#
498class _FilesystemImporter(Importer):
Greg Stein3bb578c2000-02-18 13:04:10 +0000499 def __init__(self):
500 self.suffixes = [ ]
501
502 def add_suffix(self, suffix, importFunc):
503 assert callable(importFunc)
504 self.suffixes.append((suffix, importFunc))
Greg Steinf23aa1e2000-01-03 02:38:29 +0000505
506 def import_from_dir(self, dir, fqname):
507 result = self._import_pathname(_os_path_join(dir, fqname), fqname)
508 if result:
509 return self._process_result(result, fqname)
510 return None
511
512 def get_code(self, parent, modname, fqname):
513 # This importer is never used with an empty parent. Its existence is
514 # private to the ImportManager. The ImportManager uses the
515 # import_from_dir() method to import top-level modules/packages.
516 # This method is only used when we look for a module within a package.
517 assert parent
518
519 return self._import_pathname(_os_path_join(parent.__pkgdir__, modname),
520 fqname)
521
522 def _import_pathname(self, pathname, fqname):
523 if _os_path_isdir(pathname):
524 result = self._import_pathname(_os_path_join(pathname, '__init__'),
525 fqname)
526 if result:
527 values = result[2]
528 values['__pkgdir__'] = pathname
529 values['__path__'] = [ pathname ]
530 return 1, result[1], values
531 return None
532
Greg Stein3bb578c2000-02-18 13:04:10 +0000533 for suffix, importFunc in self.suffixes:
Greg Steinf23aa1e2000-01-03 02:38:29 +0000534 filename = pathname + suffix
535 try:
536 finfo = _os_stat(filename)
537 except OSError:
538 pass
539 else:
Greg Stein3bb578c2000-02-18 13:04:10 +0000540 return importFunc(filename, finfo, fqname)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000541 return None
542
543######################################################################
544#
545# SUFFIX-BASED IMPORTERS
546#
547
Greg Stein3bb578c2000-02-18 13:04:10 +0000548def py_suffix_importer(filename, finfo, fqname):
549 file = filename[:-3] + _suffix
550 t_py = long(finfo[8])
551 t_pyc = _timestamp(file)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000552
Greg Stein3bb578c2000-02-18 13:04:10 +0000553 code = None
554 if t_pyc is not None and t_pyc >= t_py:
555 f = open(file, 'rb')
556 if f.read(4) == imp.get_magic():
557 t = struct.unpack('<I', f.read(4))[0]
558 if t == t_py:
559 code = marshal.load(f)
560 f.close()
561 if code is None:
562 file = filename
563 code = _compile(file, t_py)
Greg Steinf23aa1e2000-01-03 02:38:29 +0000564
Greg Stein3bb578c2000-02-18 13:04:10 +0000565 return 0, code, { '__file__' : file }
Greg Steinf23aa1e2000-01-03 02:38:29 +0000566
Greg Stein3bb578c2000-02-18 13:04:10 +0000567class DynLoadSuffixImporter:
Greg Steinf23aa1e2000-01-03 02:38:29 +0000568 def __init__(self, desc):
569 self.desc = desc
570
571 def import_file(self, filename, finfo, fqname):
572 fp = open(filename, self.desc[1])
573 module = imp.load_module(fqname, fp, filename, self.desc)
574 module.__file__ = filename
575 return 0, module, { }
576
577
578######################################################################
Greg Stein63faa011999-11-20 11:22:37 +0000579
Greg Stein63faa011999-11-20 11:22:37 +0000580def _print_importers():
581 items = sys.modules.items()
582 items.sort()
583 for name, module in items:
584 if module:
585 print name, module.__dict__.get('__importer__', '-- no importer')
586 else:
587 print name, '-- non-existent module'
588
Greg Steinf23aa1e2000-01-03 02:38:29 +0000589def _test_revamp():
590 ImportManager().install()
591 sys.path.insert(0, BuiltinImporter())
592
Greg Stein281b8d81999-11-07 12:54:45 +0000593######################################################################
Greg Stein42b9bc72000-02-19 13:36:23 +0000594
595#
596# TODO
597#
598# from Finn Bock:
599# remove use of "strop" -- not available in JPython
600# type(sys) is not a module in JPython. what to use instead?
601# imp.C_EXTENSION is not in JPython. same for get_suffixes and new_module
602#
603# given foo.py of:
604# import sys
605# sys.modules['foo'] = sys
606#
607# ---- standard import mechanism
608# >>> import foo
609# >>> foo
610# <module 'sys' (built-in)>
611#
612# ---- revamped import mechanism
613# >>> import imputil
614# >>> imputil._test_revamp()
615# >>> import foo
616# >>> foo
617# <module 'foo' from 'foo.py'>
618#
619#
620# from MAL:
621# should BuiltinImporter exist in sys.path or hard-wired in ImportManager?
622# need __path__ processing
623# performance
624# move chaining to a subclass [gjs: it's been nuked]
625# avoid strop
626# deinstall should be possible
627# query mechanism needed: is a specific Importer installed?
628# py/pyc/pyo piping hooks to filter/process these files
629# wish list:
630# distutils importer hooked to list of standard Internet repositories
631# module->file location mapper to speed FS-based imports
632# relative imports
633# keep chaining so that it can play nice with other import hooks
634#
635# from Gordon:
636# push MAL's mapper into sys.path[0] as a cache (hard-coded for apps)
637#
638# from Guido:
639# need to change sys.* references for rexec environs
640# need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy
641# watch out for sys.modules[...] == None
642# flag to force absolute imports? (speeds _determine_import_context and
643# checking for a relative module)
644# insert names of archives into sys.path (see quote below)
645# note: reload does NOT blast module dict
646# shift import mechanisms and policies around; provide for hooks, overrides
647# (see quote below)
648# add get_source stuff
649# get_topcode and get_subcode
650# CRLF handling in _compile
651# race condition in _compile
652# refactoring of os.py to deal with _os_bootstrap problem
653# any special handling to do for importing a module with a SyntaxError?
654# (e.g. clean up the traceback)
655# implement "domain" for path-type functionality using pkg namespace
656# (rather than FS-names like __path__)
657# don't use the word "private"... maybe "internal"
658#
659#
660# Guido's comments on sys.path caching:
661#
662# We could cache this in a dictionary: the ImportManager can have a
663# cache dict mapping pathnames to importer objects, and a separate
664# method for coming up with an importer given a pathname that's not yet
665# in the cache. The method should do a stat and/or look at the
666# extension to decide which importer class to use; you can register new
667# importer classes by registering a suffix or a Boolean function, plus a
668# class. If you register a new importer class, the cache is zapped.
669# The cache is independent from sys.path (but maintained per
670# ImportManager instance) so that rearrangements of sys.path do the
671# right thing. If a path is dropped from sys.path the corresponding
672# cache entry is simply no longer used.
673#
674# My/Guido's comments on factoring ImportManager and Importer:
675#
676# > However, we still have a tension occurring here:
677# >
678# > 1) implementing policy in ImportManager assists in single-point policy
679# > changes for app/rexec situations
680# > 2) implementing policy in Importer assists in package-private policy
681# > changes for normal, operating conditions
682# >
683# > I'll see if I can sort out a way to do this. Maybe the Importer class will
684# > implement the methods (which can be overridden to change policy) by
685# > delegating to ImportManager.
686#
687# Maybe also think about what kind of policies an Importer would be
688# likely to want to change. I have a feeling that a lot of the code
689# there is actually not so much policy but a *necessity* to get things
690# working given the calling conventions for the __import__ hook: whether
691# to return the head or tail of a dotted name, or when to do the "finish
692# fromlist" stuff.
693#