14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmImport utilities 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmExported classes: 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ImportManager Manage the import process 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Importer Base class for replacing standard import functions 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm BuiltinImporter Emulate the import mechanism for builtin and frozen modules 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DynLoadSuffixImporter 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom warnings import warnpy3k 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmwarnpy3k("the imputil module has been removed in Python 3.0", stacklevel=2) 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdel warnpy3k 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# note: avoid importing non-builtin modules 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport imp ### not available in Jython? 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport __builtin__ 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# for the DirectoryImporter 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport struct 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport marshal 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__all__ = ["ImportManager","Importer","BuiltinImporter"] 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_StringType = type('') 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_ModuleType = type(sys) ### doesn't work in Jython... 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass ImportManager: 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Manage the import process." 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def install(self, namespace=vars(__builtin__)): 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Install this ImportManager into the specified namespace." 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if isinstance(namespace, _ModuleType): 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm namespace = vars(namespace) 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Note: we have no notion of "chaining" 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Record the previous import hook, then install our own. 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.previous_importer = namespace['__import__'] 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.namespace = namespace 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm namespace['__import__'] = self._import_hook 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ### fix this 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm #namespace['reload'] = self._reload_hook 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def uninstall(self): 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Restore the previous import mechanism." 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.namespace['__import__'] = self.previous_importer 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def add_suffix(self, suffix, importFunc): 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert hasattr(importFunc, '__call__') 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.fs_imp.add_suffix(suffix, importFunc) 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ###################################################################### 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # PRIVATE METHODS 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm clsFilesystemImporter = None 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self, fs_imp=None): 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # we're definitely going to be importing something in the future, 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # so let's just load the OS-related facilities. 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not _os_stat: 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _os_bootstrap() 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This is the Importer that we use for grabbing stuff from the 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # filesystem. It defines one more method (import_from_dir) for our use. 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if fs_imp is None: 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cls = self.clsFilesystemImporter or _FilesystemImporter 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fs_imp = cls() 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.fs_imp = fs_imp 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Initialize the set of suffixes that we recognize and import. 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The default will import dynamic-load modules first, followed by 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # .py files (or a .py file's cached bytecode) 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for desc in imp.get_suffixes(): 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if desc[2] == imp.C_EXTENSION: 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.add_suffix(desc[0], 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm DynLoadSuffixImporter(desc).import_file) 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.add_suffix('.py', py_suffix_importer) 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _import_hook(self, fqname, globals=None, locals=None, fromlist=None): 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Python calls this hook to locate and import a module.""" 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parts = fqname.split('.') 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # determine the context of this import 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent = self._determine_import_context(globals) 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if there is a parent, then its importer should manage this import 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if parent: 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = parent.__importer__._do_import(parent, parts, fromlist) 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if module: 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return module 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # has the top module already been imported? 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm top_module = sys.modules[parts[0]] 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except KeyError: 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # look for the topmost module 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm top_module = self._import_top_module(parts[0]) 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not top_module: 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the topmost module wasn't found at all. 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ImportError, 'No module named ' + fqname 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # fast-path simple imports 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if len(parts) == 1: 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not fromlist: 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return top_module 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not top_module.__dict__.get('__ispkg__'): 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # __ispkg__ isn't defined (the module was not imported by us), 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # or it is zero. 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # In the former case, there is no way that we could import 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # sub-modules that occur in the fromlist (but we can't raise an 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # error because it may just be names) because we don't know how 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # to deal with packages that were imported by other systems. 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # In the latter case (__ispkg__ == 0), there can't be any sub- 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # modules present, so we can just return. 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # In both cases, since len(parts) == 1, the top_module is also 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the "bottom" which is the defined return when a fromlist 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # exists. 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return top_module 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm importer = top_module.__dict__.get('__importer__') 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if importer: 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return importer._finish_import(top_module, parts[1:], fromlist) 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Grrr, some people "import os.path" or do "from os.path import ..." 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if len(parts) == 2 and hasattr(top_module, parts[1]): 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if fromlist: 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return getattr(top_module, parts[1]) 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return top_module 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # If the importer does not exist, then we have to bail. A missing 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # importer means that something else imported the module, and we have 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # no knowledge of how to get sub-modules out of the thing. 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ImportError, 'No module named ' + fqname 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _determine_import_context(self, globals): 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Returns the context in which a module should be imported. 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The context could be a loaded (package) module and the imported module 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm will be looked for within that package. The context could also be None, 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm meaning there is no context -- the module should be looked for as a 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "top-level" module. 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not globals or not globals.get('__importer__'): 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # globals does not refer to one of our modules or packages. That 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # implies there is no relative import context (as far as we are 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # concerned), and it should just pick it off the standard path. 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # The globals refer to a module or package of ours. It will define 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the context of the new import. Get the module/package fqname. 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent_fqname = globals['__name__'] 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if a package is performing the import, then return itself (imports 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # refer to pkg contents) 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if globals['__ispkg__']: 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent = sys.modules[parent_fqname] 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert globals is parent.__dict__ 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return parent 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = parent_fqname.rfind('.') 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # a module outside of a package has no particular import context 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if i == -1: 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if a module in a package is performing the import, then return the 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # package (imports refer to siblings) 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent_fqname = parent_fqname[:i] 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent = sys.modules[parent_fqname] 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert parent.__name__ == parent_fqname 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return parent 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _import_top_module(self, name): 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # scan sys.path looking for a location in the filesystem that contains 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the module, or an Importer object that can import the module. 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for item in sys.path: 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if isinstance(item, _StringType): 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = self.fs_imp.import_from_dir(item, name) 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = item.import_top(name) 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if module: 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return module 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _reload_hook(self, module): 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Python calls this hook to reload a module." 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # reloading of a module may or may not be possible (depending on the 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # importer), but at least we can validate that it's ours to reload 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm importer = module.__dict__.get('__importer__') 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not importer: 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ### oops. now what... 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # okay. it is using the imputil system, and we must delegate it, but 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # we don't know what to do (yet) 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ### we should blast the module dict and do another get_code(). need to 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ### flesh this out and add proper docco... 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise SystemError, "reload not yet implemented" 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass Importer: 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Base class for replacing standard import functions." 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def import_top(self, name): 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Import a top-level module." 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._import_one(None, name, name) 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ###################################################################### 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # PRIVATE METHODS 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _finish_import(self, top, parts, fromlist): 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if "a.b.c" was provided, then load the ".b.c" portion down from 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # below the top-level module. 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bottom = self._load_tail(top, parts) 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if the form is "import a.b.c", then return "a" 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not fromlist: 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # no fromlist: return the top of the import tree 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return top 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the top module was imported by self. 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # this means that the bottom module was also imported by self (just 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # now, or in the past and we fetched it from sys.modules). 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # since we imported/handled the bottom module, this means that we can 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # also handle its fromlist (and reliably use __ispkg__). 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if the bottom node is a package, then (potentially) import some 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # modules. 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # note: if it is not a package, then "fromlist" refers to names in 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the bottom module rather than modules. 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # note: for a mix of names and modules in the fromlist, we will 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # import all modules and insert those into the namespace of 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the package module. Python will pick up all fromlist names 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # from the bottom (package) module; some will be modules that 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # we imported and stored in the namespace, others are expected 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # to be present already. 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if bottom.__ispkg__: 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._import_fromlist(bottom, fromlist) 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if the form is "from a.b import c, d" then return "b" 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return bottom 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _import_one(self, parent, modname, fqname): 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Import a single module." 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # has the module already been imported? 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return sys.modules[fqname] 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except KeyError: 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # load the module's code, or fetch the module itself 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = self.get_code(parent, modname, fqname) 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if result is None: 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = self._process_result(result, fqname) 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # insert the module into its parent 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if parent: 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm setattr(parent, modname, module) 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return module 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _process_result(self, result, fqname): 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ispkg, code, values = result 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # did get_code() return an actual module? (rather than a code object) 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is_module = isinstance(code, _ModuleType) 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # use the returned module, or create a new one to exec code into 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if is_module: 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = code 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = imp.new_module(fqname) 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ### record packages a bit differently?? 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module.__importer__ = self 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module.__ispkg__ = ispkg 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # insert additional values into the module (before executing the code) 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module.__dict__.update(values) 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the module is almost ready... make it visible 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.modules[fqname] = module 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # execute the code within the module's namespace 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not is_module: 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm exec code in module.__dict__ 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except: 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if fqname in sys.modules: 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del sys.modules[fqname] 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # fetch from sys.modules instead of returning module directly. 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # also make module's __name__ agree with fqname, in case 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # the "exec code in module.__dict__" played games on us. 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = sys.modules[fqname] 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module.__name__ = fqname 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return module 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _load_tail(self, m, parts): 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Import the rest of the modules, down from the top-level module. 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Returns the last module in the dotted list of modules. 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for part in parts: 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fqname = "%s.%s" % (m.__name__, part) 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm m = self._import_one(m, part, fqname) 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not m: 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ImportError, "No module named " + fqname 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return m 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _import_fromlist(self, package, fromlist): 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 'Import any sub-modules in the "from" list.' 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if '*' is present in the fromlist, then look for the '__all__' 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # variable to find additional items (modules) to import. 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if '*' in fromlist: 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fromlist = list(fromlist) + \ 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm list(package.__dict__.get('__all__', [])) 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for sub in fromlist: 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # if the name is already present, then don't try to import it (it 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # might not be a module!). 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if sub != '*' and not hasattr(package, sub): 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm subname = "%s.%s" % (package.__name__, sub) 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm submod = self._import_one(package, sub, subname) 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not submod: 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ImportError, "cannot import name " + subname 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _do_import(self, parent, parts, fromlist): 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Attempt to import the module relative to parent. 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm This method is used when the import context specifies that <self> 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm imported the parent module. 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm top_name = parts[0] 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm top_fqname = parent.__name__ + '.' + top_name 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm top_module = self._import_one(parent, top_name, top_fqname) 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not top_module: 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # this importer and parent could not find the module (relatively) 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._finish_import(top_module, parts[1:], fromlist) 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ###################################################################### 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # METHODS TO OVERRIDE 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def get_code(self, parent, modname, fqname): 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Find and retrieve the code for the given module. 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm parent specifies a parent module to define a context for importing. It 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm may be None, indicating no particular context for the search. 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modname specifies a single module (not dotted) within the parent. 3774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fqname specifies the fully-qualified module name. This is a 3794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (potentially) dotted name from the "root" of the module namespace 3804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm down to the modname. 3814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If there is no parent, then modname==fqname. 3824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm This method should return None, or a 3-tuple. 3844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * If the module was not found, then None should be returned. 3864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * The first item of the 2- or 3-tuple should be the integer 0 or 1, 3884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm specifying whether the module that was found is a package or not. 3894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * The second item is the code object for the module (it will be 3914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm executed within the new module's namespace). This item can also 3924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm be a fully-loaded module object (e.g. loaded from a shared lib). 3934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * The third item is a dictionary of name/value pairs that will be 3954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm inserted into new module before the code object is executed. This 3964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is provided in case the module's code expects certain values (such 3974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm as where the module was found). When the second item is a module 3984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm object, then these names/values will be inserted *after* the module 3994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm has been loaded/initialized. 4004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 4014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, "get_code not implemented" 4024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 4054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 4064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Some handy stuff for the Importers 4074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 4084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# byte-compiled file suffix character 4104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_suffix_char = __debug__ and 'c' or 'o' 4114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# byte-compiled file suffix 4134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_suffix = '.py' + _suffix_char 4144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _compile(pathname, timestamp): 4164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Compile (and cache) a Python source file. 4174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The file specified by <pathname> is compiled to a code object and 4194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm returned. 4204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Presuming the appropriate privileges exist, the bytecodes will be 4224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm saved back to the filesystem for future imports. The source file's 4234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm modification timestamp must be provided as a Long value. 4244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 4254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm codestring = open(pathname, 'rU').read() 4264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if codestring and codestring[-1] != '\n': 4274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm codestring = codestring + '\n' 4284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code = __builtin__.compile(codestring, pathname, 'exec') 4294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # try to cache the compiled code 4314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 4324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f = open(pathname + _suffix_char, 'wb') 4334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except IOError: 4344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 4354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 4364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.write('\0\0\0\0') 4374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.write(struct.pack('<I', timestamp)) 4384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm marshal.dump(code, f) 4394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.flush() 4404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(0, 0) 4414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.write(imp.get_magic()) 4424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.close() 4434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return code 4454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm_os_stat = _os_path_join = None 4474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _os_bootstrap(): 4484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Set up 'os' module replacement functions for use during import bootstrap." 4494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm names = sys.builtin_module_names 4514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm join = None 4534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if 'posix' in names: 4544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sep = '/' 4554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from posix import stat 4564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif 'nt' in names: 4574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sep = '\\' 4584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from nt import stat 4594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif 'dos' in names: 4604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sep = '\\' 4614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from dos import stat 4624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif 'os2' in names: 4634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sep = '\\' 4644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from os2 import stat 4654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 4664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ImportError, 'no os specific module found' 4674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if join is None: 4694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def join(a, b, sep=sep): 4704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if a == '': 4714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return b 4724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lastchar = a[-1:] 4734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if lastchar == '/' or lastchar == sep: 4744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return a + b 4754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return a + sep + b 4764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm global _os_stat 4784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _os_stat = stat 4794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm global _os_path_join 4814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _os_path_join = join 4824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _os_path_isdir(pathname): 4844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Local replacement for os.path.isdir()." 4854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 4864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = _os_stat(pathname) 4874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except OSError: 4884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 4894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return (s.st_mode & 0170000) == 0040000 4904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _timestamp(pathname): 4924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Return the file modification time as a Long." 4934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 4944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = _os_stat(pathname) 4954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except OSError: 4964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 4974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return long(s.st_mtime) 4984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 4994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 5014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Emulate the import mechanism for builtin and frozen modules 5034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BuiltinImporter(Importer): 5054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def get_code(self, parent, modname, fqname): 5064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if parent: 5074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # these modules definitely do not occur within a package context 5084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 5094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # look for the module 5114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if imp.is_builtin(modname): 5124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm type = imp.C_BUILTIN 5134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif imp.is_frozen(modname): 5144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm type = imp.PY_FROZEN 5154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 5164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # not found 5174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 5184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # got it. now load and return it. 5204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = imp.load_module(modname, None, modname, ('', '', type)) 5214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0, module, { } 5224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 5254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Internal importer used for importing from the filesystem 5274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass _FilesystemImporter(Importer): 5294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self): 5304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.suffixes = [ ] 5314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def add_suffix(self, suffix, importFunc): 5334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert hasattr(importFunc, '__call__') 5344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.suffixes.append((suffix, importFunc)) 5354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def import_from_dir(self, dir, fqname): 5374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = self._import_pathname(_os_path_join(dir, fqname), fqname) 5384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if result: 5394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._process_result(result, fqname) 5404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 5414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def get_code(self, parent, modname, fqname): 5434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This importer is never used with an empty parent. Its existence is 5444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # private to the ImportManager. The ImportManager uses the 5454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # import_from_dir() method to import top-level modules/packages. 5464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # This method is only used when we look for a module within a package. 5474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm assert parent 5484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for submodule_path in parent.__path__: 5504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code = self._import_pathname(_os_path_join(submodule_path, modname), fqname) 5514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if code is not None: 5524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return code 5534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._import_pathname(_os_path_join(parent.__pkgdir__, modname), 5544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fqname) 5554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _import_pathname(self, pathname, fqname): 5574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if _os_path_isdir(pathname): 5584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm result = self._import_pathname(_os_path_join(pathname, '__init__'), 5594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fqname) 5604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if result: 5614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm values = result[2] 5624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm values['__pkgdir__'] = pathname 5634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm values['__path__'] = [ pathname ] 5644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1, result[1], values 5654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 5664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for suffix, importFunc in self.suffixes: 5684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm filename = pathname + suffix 5694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 5704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm finfo = _os_stat(filename) 5714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except OSError: 5724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 5734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 5744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return importFunc(filename, finfo, fqname) 5754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return None 5764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 5784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# SUFFIX-BASED IMPORTERS 5804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 5814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef py_suffix_importer(filename, finfo, fqname): 5834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm file = filename[:-3] + _suffix 5844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t_py = long(finfo[8]) 5854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t_pyc = _timestamp(file) 5864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code = None 5884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if t_pyc is not None and t_pyc >= t_py: 5894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f = open(file, 'rb') 5904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if f.read(4) == imp.get_magic(): 5914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm t = struct.unpack('<I', f.read(4))[0] 5924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if t == t_py: 5934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code = marshal.load(f) 5944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.close() 5954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if code is None: 5964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm file = filename 5974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm code = _compile(file, t_py) 5984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 5994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0, code, { '__file__' : file } 6004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass DynLoadSuffixImporter: 6024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self, desc): 6034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.desc = desc 6044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def import_file(self, filename, finfo, fqname): 6064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fp = open(filename, self.desc[1]) 6074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module = imp.load_module(fqname, fp, filename, self.desc) 6084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm module.__file__ = filename 6094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0, module, { } 6104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 6134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _print_importers(): 6154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm items = sys.modules.items() 6164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm items.sort() 6174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for name, module in items: 6184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if module: 6194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print name, module.__dict__.get('__importer__', '-- no importer') 6204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 6214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print name, '-- non-existent module' 6224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _test_revamp(): 6244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ImportManager().install() 6254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sys.path.insert(0, BuiltinImporter()) 6264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm###################################################################### 6284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 6294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# TODO 6314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# from Finn Bock: 6334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# type(sys) is not a module in Jython. what to use instead? 6344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# imp.C_EXTENSION is not in Jython. same for get_suffixes and new_module 6354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# given foo.py of: 6374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# import sys 6384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# sys.modules['foo'] = sys 6394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ---- standard import mechanism 6414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> import foo 6424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> foo 6434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# <module 'sys' (built-in)> 6444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ---- revamped import mechanism 6464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> import imputil 6474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> imputil._test_revamp() 6484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> import foo 6494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# >>> foo 6504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# <module 'foo' from 'foo.py'> 6514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# from MAL: 6544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# should BuiltinImporter exist in sys.path or hard-wired in ImportManager? 6554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# need __path__ processing 6564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# performance 6574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# move chaining to a subclass [gjs: it's been nuked] 6584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# deinstall should be possible 6594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# query mechanism needed: is a specific Importer installed? 6604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# py/pyc/pyo piping hooks to filter/process these files 6614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# wish list: 6624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# distutils importer hooked to list of standard Internet repositories 6634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# module->file location mapper to speed FS-based imports 6644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# relative imports 6654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# keep chaining so that it can play nice with other import hooks 6664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# from Gordon: 6684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# push MAL's mapper into sys.path[0] as a cache (hard-coded for apps) 6694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# from Guido: 6714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# need to change sys.* references for rexec environs 6724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# need hook for MAL's walk-me-up import strategy, or Tim's absolute strategy 6734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# watch out for sys.modules[...] is None 6744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# flag to force absolute imports? (speeds _determine_import_context and 6754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# checking for a relative module) 6764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# insert names of archives into sys.path (see quote below) 6774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# note: reload does NOT blast module dict 6784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# shift import mechanisms and policies around; provide for hooks, overrides 6794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (see quote below) 6804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# add get_source stuff 6814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# get_topcode and get_subcode 6824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# CRLF handling in _compile 6834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# race condition in _compile 6844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# refactoring of os.py to deal with _os_bootstrap problem 6854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# any special handling to do for importing a module with a SyntaxError? 6864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (e.g. clean up the traceback) 6874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# implement "domain" for path-type functionality using pkg namespace 6884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# (rather than FS-names like __path__) 6894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# don't use the word "private"... maybe "internal" 6904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Guido's comments on sys.path caching: 6934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 6944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# We could cache this in a dictionary: the ImportManager can have a 6954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# cache dict mapping pathnames to importer objects, and a separate 6964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# method for coming up with an importer given a pathname that's not yet 6974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# in the cache. The method should do a stat and/or look at the 6984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# extension to decide which importer class to use; you can register new 6994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# importer classes by registering a suffix or a Boolean function, plus a 7004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# class. If you register a new importer class, the cache is zapped. 7014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# The cache is independent from sys.path (but maintained per 7024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# ImportManager instance) so that rearrangements of sys.path do the 7034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# right thing. If a path is dropped from sys.path the corresponding 7044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# cache entry is simply no longer used. 7054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 7064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# My/Guido's comments on factoring ImportManager and Importer: 7074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 7084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > However, we still have a tension occurring here: 7094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > 7104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > 1) implementing policy in ImportManager assists in single-point policy 7114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > changes for app/rexec situations 7124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > 2) implementing policy in Importer assists in package-private policy 7134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > changes for normal, operating conditions 7144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > 7154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > I'll see if I can sort out a way to do this. Maybe the Importer class will 7164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > implement the methods (which can be overridden to change policy) by 7174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# > delegating to ImportManager. 7184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 7194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Maybe also think about what kind of policies an Importer would be 7204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# likely to want to change. I have a feeling that a lot of the code 7214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# there is actually not so much policy but a *necessity* to get things 7224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# working given the calling conventions for the __import__ hook: whether 7234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# to return the head or tail of a dotted name, or when to do the "finish 7244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# fromlist" stuff. 7254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# 726