mirror of
https://github.com/python/cpython.git
synced 2025-07-09 20:35:26 +00:00
Issue #15641: Clean up deprecated classes from importlib
Patch by Taras Lyapun.
This commit is contained in:
parent
bcbf4036c9
commit
90a654b1dd
5 changed files with 7 additions and 834 deletions
|
@ -225,180 +225,3 @@ class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader):
|
|||
raise NotImplementedError
|
||||
|
||||
_register(SourceLoader, machinery.SourceFileLoader)
|
||||
|
||||
class PyLoader(SourceLoader):
|
||||
|
||||
"""Implement the deprecated PyLoader ABC in terms of SourceLoader.
|
||||
|
||||
This class has been deprecated! It is slated for removal in Python 3.4.
|
||||
If compatibility with Python 3.1 is not needed then implement the
|
||||
SourceLoader ABC instead of this class. If Python 3.1 compatibility is
|
||||
needed, then use the following idiom to have a single class that is
|
||||
compatible with Python 3.1 onwards::
|
||||
|
||||
try:
|
||||
from importlib.abc import SourceLoader
|
||||
except ImportError:
|
||||
from importlib.abc import PyLoader as SourceLoader
|
||||
|
||||
|
||||
class CustomLoader(SourceLoader):
|
||||
def get_filename(self, fullname):
|
||||
# Implement ...
|
||||
|
||||
def source_path(self, fullname):
|
||||
'''Implement source_path in terms of get_filename.'''
|
||||
try:
|
||||
return self.get_filename(fullname)
|
||||
except ImportError:
|
||||
return None
|
||||
|
||||
def is_package(self, fullname):
|
||||
filename = os.path.basename(self.get_filename(fullname))
|
||||
return os.path.splitext(filename)[0] == '__init__'
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_package(self, fullname):
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def source_path(self, fullname):
|
||||
"""Abstract method. Accepts a str module name and returns the path to
|
||||
the source code for the module."""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_filename(self, fullname):
|
||||
"""Implement get_filename in terms of source_path.
|
||||
|
||||
As get_filename should only return a source file path there is no
|
||||
chance of the path not existing but loading still being possible, so
|
||||
ImportError should propagate instead of being turned into returning
|
||||
None.
|
||||
|
||||
"""
|
||||
warnings.warn("importlib.abc.PyLoader is deprecated and is "
|
||||
"slated for removal in Python 3.4; "
|
||||
"use SourceLoader instead. "
|
||||
"See the importlib documentation on how to be "
|
||||
"compatible with Python 3.1 onwards.",
|
||||
DeprecationWarning)
|
||||
path = self.source_path(fullname)
|
||||
if path is None:
|
||||
raise ImportError(name=fullname)
|
||||
else:
|
||||
return path
|
||||
|
||||
|
||||
class PyPycLoader(PyLoader):
|
||||
|
||||
"""Abstract base class to assist in loading source and bytecode by
|
||||
requiring only back-end storage methods to be implemented.
|
||||
|
||||
This class has been deprecated! Removal is slated for Python 3.4. Implement
|
||||
the SourceLoader ABC instead. If Python 3.1 compatibility is needed, see
|
||||
PyLoader.
|
||||
|
||||
The methods get_code, get_source, and load_module are implemented for the
|
||||
user.
|
||||
|
||||
"""
|
||||
|
||||
def get_filename(self, fullname):
|
||||
"""Return the source or bytecode file path."""
|
||||
path = self.source_path(fullname)
|
||||
if path is not None:
|
||||
return path
|
||||
path = self.bytecode_path(fullname)
|
||||
if path is not None:
|
||||
return path
|
||||
raise ImportError("no source or bytecode path available for "
|
||||
"{0!r}".format(fullname), name=fullname)
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Get a code object from source or bytecode."""
|
||||
warnings.warn("importlib.abc.PyPycLoader is deprecated and slated for "
|
||||
"removal in Python 3.4; use SourceLoader instead. "
|
||||
"If Python 3.1 compatibility is required, see the "
|
||||
"latest documentation for PyLoader.",
|
||||
DeprecationWarning)
|
||||
source_timestamp = self.source_mtime(fullname)
|
||||
# Try to use bytecode if it is available.
|
||||
bytecode_path = self.bytecode_path(fullname)
|
||||
if bytecode_path:
|
||||
data = self.get_data(bytecode_path)
|
||||
try:
|
||||
magic = data[:4]
|
||||
if len(magic) < 4:
|
||||
raise ImportError(
|
||||
"bad magic number in {}".format(fullname),
|
||||
name=fullname, path=bytecode_path)
|
||||
raw_timestamp = data[4:8]
|
||||
if len(raw_timestamp) < 4:
|
||||
raise EOFError("bad timestamp in {}".format(fullname))
|
||||
pyc_timestamp = _bootstrap._r_long(raw_timestamp)
|
||||
raw_source_size = data[8:12]
|
||||
if len(raw_source_size) != 4:
|
||||
raise EOFError("bad file size in {}".format(fullname))
|
||||
# Source size is unused as the ABC does not provide a way to
|
||||
# get the size of the source ahead of reading it.
|
||||
bytecode = data[12:]
|
||||
# Verify that the magic number is valid.
|
||||
if imp.get_magic() != magic:
|
||||
raise ImportError(
|
||||
"bad magic number in {}".format(fullname),
|
||||
name=fullname, path=bytecode_path)
|
||||
# Verify that the bytecode is not stale (only matters when
|
||||
# there is source to fall back on.
|
||||
if source_timestamp:
|
||||
if pyc_timestamp < source_timestamp:
|
||||
raise ImportError("bytecode is stale", name=fullname,
|
||||
path=bytecode_path)
|
||||
except (ImportError, EOFError):
|
||||
# If source is available give it a shot.
|
||||
if source_timestamp is not None:
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
# Bytecode seems fine, so try to use it.
|
||||
return marshal.loads(bytecode)
|
||||
elif source_timestamp is None:
|
||||
raise ImportError("no source or bytecode available to create code "
|
||||
"object for {0!r}".format(fullname),
|
||||
name=fullname)
|
||||
# Use the source.
|
||||
source_path = self.source_path(fullname)
|
||||
if source_path is None:
|
||||
message = "a source path must exist to load {0}".format(fullname)
|
||||
raise ImportError(message, name=fullname)
|
||||
source = self.get_data(source_path)
|
||||
code_object = compile(source, source_path, 'exec', dont_inherit=True)
|
||||
# Generate bytecode and write it out.
|
||||
if not sys.dont_write_bytecode:
|
||||
data = bytearray(imp.get_magic())
|
||||
data.extend(_bootstrap._w_long(source_timestamp))
|
||||
data.extend(_bootstrap._w_long(len(source) & 0xFFFFFFFF))
|
||||
data.extend(marshal.dumps(code_object))
|
||||
self.write_bytecode(fullname, data)
|
||||
return code_object
|
||||
|
||||
@abc.abstractmethod
|
||||
def source_mtime(self, fullname):
|
||||
"""Abstract method. Accepts a str filename and returns an int
|
||||
modification time for the source of the module."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def bytecode_path(self, fullname):
|
||||
"""Abstract method. Accepts a str filename and returns the str pathname
|
||||
to the bytecode for the module."""
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def write_bytecode(self, fullname, bytecode):
|
||||
"""Abstract method. Accepts a str filename and bytes object
|
||||
representing the bytecode for the module. Returns a boolean
|
||||
representing whether the bytecode was written or not."""
|
||||
raise NotImplementedError
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue