"""Implementation of Python's import machinery in Python source code. The Import class implements the semantics of import. This means that an instance of this class can be called to properly check sys.modules, sys.meta_path, sys.path, etc. to import the requested module. The importing of built-in, frozen, extension, .py, and .pyc files are all handled by implementing importers and loaders as specified by PEP 302. This leads to the ability to easily control imports based on the type of module. There is also a clear distinction between how the module is stored and how it is formatted (e.g., a Python source file does not require it be stored as a file on a filesystem). To help with the distinction between how a module is stored compared to its format the idea of handlers is introduced. A handler implements a specific interface while specifying the type of module it handles (usually by the what one would expect as a file extension if the module was on a filesystem). This allows a PEP 302 importer/loader to represent how a module is stored while the handler deals with how the module is formatted. A handler is expected to implement the handle_code method only. The handler for Python source and bytecode modules goes farther and defines an extensive interface that is designed so that alternatives on module formatting can be supported easily without needing to write a new importer/loader. The Python source and bytecode handler also expects loaders to define a more extensive interface to allow for different backend stores (e.g., databases) to use the handler without modification. All of this helps with code reuse and possible errors from the complicated relationship between Python source and bytecode modules. """ import _importlib # XXX Temporary functions that should eventually be removed. import os def _set__import__(): """Set __import__ to an instance of Import.""" global original__import__ original__import__ = __import__ __builtins__['__import__'] = Import() def _reset__import__(): """Set __import__ back to the original implementation (assumes _set__import__ was called previously).""" __builtins__['__import__'] = original__import__ def _w_long(x): """Convert a 32-bit integer to little-endian. XXX Temporary until marshal's long functions are exposed. """ x = int(x) int_bytes = [] int_bytes.append(x & 0xFF) int_bytes.append((x >> 8) & 0xFF) int_bytes.append((x >> 16) & 0xFF) int_bytes.append((x >> 24) & 0xFF) return ''.join(chr(x) for x in int_bytes) def _r_long(int_bytes): """Convert 4 bytes in little-endian to an integer. XXX Temporary until marshal's long function are exposed. """ x = ord(int_bytes[0]) x |= ord(int_bytes[1]) << 8 x |= ord(int_bytes[2]) << 16 x |= ord(int_bytes[3]) << 24 return x def _case_ok(directory, file_name): """Verify that file_name (as found in 'directory') has the proper case. The path is assumed to already exist. XXX Temporary until imp's case_ok function can be exposed. XXX Better to roll this into a single function some how so that existence check can be part of case check and thus cut down on stat calls? """ # If platform is not case-sensitive *or* the environment variable # PYTHONCASEOK is defined, then os.path.exists already handled the case by # either doing a case-sensitive check or from the user saying he does not # want case-sensitivity, respectively. if sys.platform not in ('win32', 'mac', 'riscos', 'darwin', 'cygwin', 'os2emx') or os.environ.get('PYTHONCASEOK'): return True directory_contents = set(os.path.splitext(x)[0] for x in os.listdir(directory)) file_wo_ext = os.path.splitext(file_name)[0] if file_wo_ext in directory_contents: return True else: return False # Required built-in modules. try: import posix as _os except ImportError: try: import nt as _os except ImportError: try: import os2 as _os except ImportError: raise ImportError('posix, nt, or os2 module required for importlib') _importlib._os = _os import imp, sys, marshal, errno _importlib.imp = imp _importlib.sys = sys _importlib.marshal = marshal _importlib.errno = errno # XXX 'warnings' needs become a built-in module (Neal). import warnings _importlib.warnings = warnings from os import sep _importlib._r_long = _r_long #XXX Expose original from marshal. _importlib._w_long = _w_long #XXX Expose original from marshal. _importlib._case_ok = _case_ok #XXX Expose original from imp. # For os.path.join replacement; pull from Include/osdefs.h:SEP . _importlib.path_sep = sep del _importlib from _importlib import *