mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	and relies much more on meta path finders to abstract out various parts of import. As part of this the semantics for import_module tightened up and now follow __import__ much more closely (biggest thing is that the 'package' argument must now already be imported, else a SystemError is raised).
		
			
				
	
	
		
			140 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""A pure Python implementation of import.
 | 
						|
 | 
						|
References on import:
 | 
						|
 | 
						|
    * Language reference
 | 
						|
          http://docs.python.org/ref/import.html
 | 
						|
    * __import__ function
 | 
						|
          http://docs.python.org/lib/built-in-funcs.html
 | 
						|
    * Packages
 | 
						|
          http://www.python.org/doc/essays/packages.html
 | 
						|
    * PEP 235: Import on Case-Insensitive Platforms
 | 
						|
          http://www.python.org/dev/peps/pep-0235
 | 
						|
    * PEP 275: Import Modules from Zip Archives
 | 
						|
          http://www.python.org/dev/peps/pep-0273
 | 
						|
    * PEP 302: New Import Hooks
 | 
						|
          http://www.python.org/dev/peps/pep-0302/
 | 
						|
    * PEP 328: Imports: Multi-line and Absolute/Relative
 | 
						|
          http://www.python.org/dev/peps/pep-0328
 | 
						|
 | 
						|
"""
 | 
						|
from . import _bootstrap
 | 
						|
 | 
						|
# XXX Temporary functions that should eventually be removed.
 | 
						|
import os
 | 
						|
import re
 | 
						|
import tokenize
 | 
						|
 | 
						|
def _set__import__():
 | 
						|
    """Set __import__ to an instance of Import."""
 | 
						|
    global original__import__
 | 
						|
    original__import__ = __import__
 | 
						|
    __builtins__['__import__'] = _bootstrap._import
 | 
						|
 | 
						|
 | 
						|
def _reset__import__():
 | 
						|
    """Set __import__ back to the original implementation (assumes
 | 
						|
    _set__import__ was called previously)."""
 | 
						|
    __builtins__['__import__'] = original__import__
 | 
						|
 | 
						|
 | 
						|
# Bootstrap help #####################################################
 | 
						|
 | 
						|
def _case_ok(directory, check):
 | 
						|
    """Check if the directory contains something matching 'check'.
 | 
						|
 | 
						|
    No check is done if the file/directory exists or not.
 | 
						|
 | 
						|
    """
 | 
						|
    if 'PYTHONCASEOK' in os.environ:
 | 
						|
        return True
 | 
						|
    elif check in os.listdir(directory):
 | 
						|
        return True
 | 
						|
    return False
 | 
						|
 | 
						|
 | 
						|
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 bytearray(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 = int_bytes[0]
 | 
						|
    x |= int_bytes[1] << 8
 | 
						|
    x |= int_bytes[2] << 16
 | 
						|
    x |= int_bytes[3] << 24
 | 
						|
    return x
 | 
						|
 | 
						|
 | 
						|
# 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')
 | 
						|
_bootstrap._os = _os
 | 
						|
import imp, sys, marshal, errno, _fileio
 | 
						|
_bootstrap.imp = imp
 | 
						|
_bootstrap.sys = sys
 | 
						|
_bootstrap.marshal = marshal
 | 
						|
_bootstrap.errno = errno
 | 
						|
_bootstrap._fileio = _fileio
 | 
						|
import _warnings
 | 
						|
_bootstrap._warnings = _warnings
 | 
						|
 | 
						|
 | 
						|
from os import sep
 | 
						|
# For os.path.join replacement; pull from Include/osdefs.h:SEP .
 | 
						|
_bootstrap.path_sep = sep
 | 
						|
 | 
						|
_bootstrap._case_ok = _case_ok
 | 
						|
marshal._w_long = _w_long
 | 
						|
marshal._r_long = _r_long
 | 
						|
 | 
						|
 | 
						|
# Public API #########################################################
 | 
						|
 | 
						|
__import__ = _bootstrap._import
 | 
						|
 | 
						|
 | 
						|
def import_module(name, package=None):
 | 
						|
    """Import a module.
 | 
						|
 | 
						|
    The 'package' argument is required when performing a relative import. It
 | 
						|
    specifies the package to use as the anchor point from which to resolve the
 | 
						|
    relative import to an absolute import.
 | 
						|
 | 
						|
    """
 | 
						|
    level = 0
 | 
						|
    if name.startswith('.'):
 | 
						|
        if not package:
 | 
						|
            raise TypeError("relative imports require the 'package' argument")
 | 
						|
        for character in name:
 | 
						|
            if character != '.':
 | 
						|
                break
 | 
						|
            level += 1
 | 
						|
    return _bootstrap._gcd_import(name[level:], package, level)
 | 
						|
 | 
						|
 | 
						|
# XXX This should go away once the public API is done.
 | 
						|
from ._bootstrap import *
 |