Skip to content

Commit 90a654b

Browse files
committed
Issue #15641: Clean up deprecated classes from importlib
Patch by Taras Lyapun.
1 parent bcbf403 commit 90a654b

5 files changed

Lines changed: 7 additions & 834 deletions

File tree

Doc/library/importlib.rst

Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@ ABC hierarchy::
133133
+-- ExecutionLoader --+
134134
+-- FileLoader
135135
+-- SourceLoader
136-
+-- PyLoader (deprecated)
137-
+-- PyPycLoader (deprecated)
138136

139137

140138
.. class:: Finder
@@ -431,142 +429,6 @@ ABC hierarchy::
431429
itself does not end in ``__init__``.
432430

433431

434-
.. class:: PyLoader
435-
436-
An abstract base class inheriting from
437-
:class:`ExecutionLoader` and
438-
:class:`ResourceLoader` designed to ease the loading of
439-
Python source modules (bytecode is not handled; see
440-
:class:`SourceLoader` for a source/bytecode ABC). A subclass
441-
implementing this ABC will only need to worry about exposing how the source
442-
code is stored; all other details for loading Python source code will be
443-
handled by the concrete implementations of key methods.
444-
445-
.. deprecated:: 3.2
446-
This class has been deprecated in favor of :class:`SourceLoader` and is
447-
slated for removal in Python 3.4. See below for how to create a
448-
subclass that is compatible with Python 3.1 onwards.
449-
450-
If compatibility with Python 3.1 is required, then use the following idiom
451-
to implement a subclass that will work with Python 3.1 onwards (make sure
452-
to implement :meth:`ExecutionLoader.get_filename`)::
453-
454-
try:
455-
from importlib.abc import SourceLoader
456-
except ImportError:
457-
from importlib.abc import PyLoader as SourceLoader
458-
459-
460-
class CustomLoader(SourceLoader):
461-
def get_filename(self, fullname):
462-
"""Return the path to the source file."""
463-
# Implement ...
464-
465-
def source_path(self, fullname):
466-
"""Implement source_path in terms of get_filename."""
467-
try:
468-
return self.get_filename(fullname)
469-
except ImportError:
470-
return None
471-
472-
def is_package(self, fullname):
473-
"""Implement is_package by looking for an __init__ file
474-
name as returned by get_filename."""
475-
filename = os.path.basename(self.get_filename(fullname))
476-
return os.path.splitext(filename)[0] == '__init__'
477-
478-
479-
.. method:: source_path(fullname)
480-
481-
An abstract method that returns the path to the source code for a
482-
module. Should return ``None`` if there is no source code.
483-
Raises :exc:`ImportError` if the loader knows it cannot handle the
484-
module.
485-
486-
.. method:: get_filename(fullname)
487-
488-
A concrete implementation of
489-
:meth:`importlib.abc.ExecutionLoader.get_filename` that
490-
relies on :meth:`source_path`. If :meth:`source_path` returns
491-
``None``, then :exc:`ImportError` is raised.
492-
493-
.. method:: load_module(fullname)
494-
495-
A concrete implementation of :meth:`importlib.abc.Loader.load_module`
496-
that loads Python source code. All needed information comes from the
497-
abstract methods required by this ABC. The only pertinent assumption
498-
made by this method is that when loading a package
499-
:attr:`__path__` is set to ``[os.path.dirname(__file__)]``.
500-
501-
.. method:: get_code(fullname)
502-
503-
A concrete implementation of
504-
:meth:`importlib.abc.InspectLoader.get_code` that creates code objects
505-
from Python source code, by requesting the source code (using
506-
:meth:`source_path` and :meth:`get_data`) and compiling it with the
507-
built-in :func:`compile` function.
508-
509-
.. method:: get_source(fullname)
510-
511-
A concrete implementation of
512-
:meth:`importlib.abc.InspectLoader.get_source`. Uses
513-
:meth:`importlib.abc.ResourceLoader.get_data` and :meth:`source_path`
514-
to get the source code. It tries to guess the source encoding using
515-
:func:`tokenize.detect_encoding`.
516-
517-
518-
.. class:: PyPycLoader
519-
520-
An abstract base class inheriting from :class:`PyLoader`.
521-
This ABC is meant to help in creating loaders that support both Python
522-
source and bytecode.
523-
524-
.. deprecated:: 3.2
525-
This class has been deprecated in favor of :class:`SourceLoader` and to
526-
properly support :pep:`3147`. If compatibility is required with
527-
Python 3.1, implement both :class:`SourceLoader` and :class:`PyLoader`;
528-
instructions on how to do so are included in the documentation for
529-
:class:`PyLoader`. Do note that this solution will not support
530-
sourceless/bytecode-only loading; only source *and* bytecode loading.
531-
532-
.. versionchanged:: 3.3
533-
Updated to parse (but not use) the new source size field in bytecode
534-
files when reading and to write out the field properly when writing.
535-
536-
.. method:: source_mtime(fullname)
537-
538-
An abstract method which returns the modification time for the source
539-
code of the specified module. The modification time should be an
540-
integer. If there is no source code, return ``None``. If the
541-
module cannot be found then :exc:`ImportError` is raised.
542-
543-
.. method:: bytecode_path(fullname)
544-
545-
An abstract method which returns the path to the bytecode for the
546-
specified module, if it exists. It returns ``None``
547-
if no bytecode exists (yet).
548-
Raises :exc:`ImportError` if the loader knows it cannot handle the
549-
module.
550-
551-
.. method:: get_filename(fullname)
552-
553-
A concrete implementation of
554-
:meth:`ExecutionLoader.get_filename` that relies on
555-
:meth:`PyLoader.source_path` and :meth:`bytecode_path`.
556-
If :meth:`source_path` returns a path, then that value is returned.
557-
Else if :meth:`bytecode_path` returns a path, that path will be
558-
returned. If a path is not available from both methods,
559-
:exc:`ImportError` is raised.
560-
561-
.. method:: write_bytecode(fullname, bytecode)
562-
563-
An abstract method which has the loader write *bytecode* for future
564-
use. If the bytecode is written, return ``True``. Return
565-
``False`` if the bytecode could not be written. This method
566-
should not be called if :data:`sys.dont_write_bytecode` is true.
567-
The *bytecode* argument should be a bytes string or bytes array.
568-
569-
570432
:mod:`importlib.machinery` -- Importers and path hooks
571433
------------------------------------------------------
572434

Lib/importlib/abc.py

Lines changed: 0 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -225,180 +225,3 @@ def set_data(self, path, data):
225225
raise NotImplementedError
226226

227227
_register(SourceLoader, machinery.SourceFileLoader)
228-
229-
class PyLoader(SourceLoader):
230-
231-
"""Implement the deprecated PyLoader ABC in terms of SourceLoader.
232-
233-
This class has been deprecated! It is slated for removal in Python 3.4.
234-
If compatibility with Python 3.1 is not needed then implement the
235-
SourceLoader ABC instead of this class. If Python 3.1 compatibility is
236-
needed, then use the following idiom to have a single class that is
237-
compatible with Python 3.1 onwards::
238-
239-
try:
240-
from importlib.abc import SourceLoader
241-
except ImportError:
242-
from importlib.abc import PyLoader as SourceLoader
243-
244-
245-
class CustomLoader(SourceLoader):
246-
def get_filename(self, fullname):
247-
# Implement ...
248-
249-
def source_path(self, fullname):
250-
'''Implement source_path in terms of get_filename.'''
251-
try:
252-
return self.get_filename(fullname)
253-
except ImportError:
254-
return None
255-
256-
def is_package(self, fullname):
257-
filename = os.path.basename(self.get_filename(fullname))
258-
return os.path.splitext(filename)[0] == '__init__'
259-
260-
"""
261-
262-
@abc.abstractmethod
263-
def is_package(self, fullname):
264-
raise NotImplementedError
265-
266-
@abc.abstractmethod
267-
def source_path(self, fullname):
268-
"""Abstract method. Accepts a str module name and returns the path to
269-
the source code for the module."""
270-
raise NotImplementedError
271-
272-
def get_filename(self, fullname):
273-
"""Implement get_filename in terms of source_path.
274-
275-
As get_filename should only return a source file path there is no
276-
chance of the path not existing but loading still being possible, so
277-
ImportError should propagate instead of being turned into returning
278-
None.
279-
280-
"""
281-
warnings.warn("importlib.abc.PyLoader is deprecated and is "
282-
"slated for removal in Python 3.4; "
283-
"use SourceLoader instead. "
284-
"See the importlib documentation on how to be "
285-
"compatible with Python 3.1 onwards.",
286-
DeprecationWarning)
287-
path = self.source_path(fullname)
288-
if path is None:
289-
raise ImportError(name=fullname)
290-
else:
291-
return path
292-
293-
294-
class PyPycLoader(PyLoader):
295-
296-
"""Abstract base class to assist in loading source and bytecode by
297-
requiring only back-end storage methods to be implemented.
298-
299-
This class has been deprecated! Removal is slated for Python 3.4. Implement
300-
the SourceLoader ABC instead. If Python 3.1 compatibility is needed, see
301-
PyLoader.
302-
303-
The methods get_code, get_source, and load_module are implemented for the
304-
user.
305-
306-
"""
307-
308-
def get_filename(self, fullname):
309-
"""Return the source or bytecode file path."""
310-
path = self.source_path(fullname)
311-
if path is not None:
312-
return path
313-
path = self.bytecode_path(fullname)
314-
if path is not None:
315-
return path
316-
raise ImportError("no source or bytecode path available for "
317-
"{0!r}".format(fullname), name=fullname)
318-
319-
def get_code(self, fullname):
320-
"""Get a code object from source or bytecode."""
321-
warnings.warn("importlib.abc.PyPycLoader is deprecated and slated for "
322-
"removal in Python 3.4; use SourceLoader instead. "
323-
"If Python 3.1 compatibility is required, see the "
324-
"latest documentation for PyLoader.",
325-
DeprecationWarning)
326-
source_timestamp = self.source_mtime(fullname)
327-
# Try to use bytecode if it is available.
328-
bytecode_path = self.bytecode_path(fullname)
329-
if bytecode_path:
330-
data = self.get_data(bytecode_path)
331-
try:
332-
magic = data[:4]
333-
if len(magic) < 4:
334-
raise ImportError(
335-
"bad magic number in {}".format(fullname),
336-
name=fullname, path=bytecode_path)
337-
raw_timestamp = data[4:8]
338-
if len(raw_timestamp) < 4:
339-
raise EOFError("bad timestamp in {}".format(fullname))
340-
pyc_timestamp = _bootstrap._r_long(raw_timestamp)
341-
raw_source_size = data[8:12]
342-
if len(raw_source_size) != 4:
343-
raise EOFError("bad file size in {}".format(fullname))
344-
# Source size is unused as the ABC does not provide a way to
345-
# get the size of the source ahead of reading it.
346-
bytecode = data[12:]
347-
# Verify that the magic number is valid.
348-
if imp.get_magic() != magic:
349-
raise ImportError(
350-
"bad magic number in {}".format(fullname),
351-
name=fullname, path=bytecode_path)
352-
# Verify that the bytecode is not stale (only matters when
353-
# there is source to fall back on.
354-
if source_timestamp:
355-
if pyc_timestamp < source_timestamp:
356-
raise ImportError("bytecode is stale", name=fullname,
357-
path=bytecode_path)
358-
except (ImportError, EOFError):
359-
# If source is available give it a shot.
360-
if source_timestamp is not None:
361-
pass
362-
else:
363-
raise
364-
else:
365-
# Bytecode seems fine, so try to use it.
366-
return marshal.loads(bytecode)
367-
elif source_timestamp is None:
368-
raise ImportError("no source or bytecode available to create code "
369-
"object for {0!r}".format(fullname),
370-
name=fullname)
371-
# Use the source.
372-
source_path = self.source_path(fullname)
373-
if source_path is None:
374-
message = "a source path must exist to load {0}".format(fullname)
375-
raise ImportError(message, name=fullname)
376-
source = self.get_data(source_path)
377-
code_object = compile(source, source_path, 'exec', dont_inherit=True)
378-
# Generate bytecode and write it out.
379-
if not sys.dont_write_bytecode:
380-
data = bytearray(imp.get_magic())
381-
data.extend(_bootstrap._w_long(source_timestamp))
382-
data.extend(_bootstrap._w_long(len(source) & 0xFFFFFFFF))
383-
data.extend(marshal.dumps(code_object))
384-
self.write_bytecode(fullname, data)
385-
return code_object
386-
387-
@abc.abstractmethod
388-
def source_mtime(self, fullname):
389-
"""Abstract method. Accepts a str filename and returns an int
390-
modification time for the source of the module."""
391-
raise NotImplementedError
392-
393-
@abc.abstractmethod
394-
def bytecode_path(self, fullname):
395-
"""Abstract method. Accepts a str filename and returns the str pathname
396-
to the bytecode for the module."""
397-
raise NotImplementedError
398-
399-
@abc.abstractmethod
400-
def write_bytecode(self, fullname, bytecode):
401-
"""Abstract method. Accepts a str filename and bytes object
402-
representing the bytecode for the module. Returns a boolean
403-
representing whether the bytecode was written or not."""
404-
raise NotImplementedError

0 commit comments

Comments
 (0)