Commit 100883f0 authored by Brett Cannon's avatar Brett Cannon

Issue #17093,17566,17567: Methods from classes in importlib.abc now raise/return

the default exception/value when called instead of raising/returning
NotimplementedError/NotImplemented (except where appropriate).
This should allow for the ABCs to act as the bottom/end of the MRO with expected
default results.

As part of this work, also make importlib.abc.Loader.module_repr()
optional instead of an abstractmethod.
parent 0f344b6e
......@@ -153,6 +153,10 @@ ABC hierarchy::
module. Originally specified in :pep:`302`, this method was meant
for use in :data:`sys.meta_path` and in the path-based import subsystem.
.. versionchanged:: 3.4
Returns ``None`` when called instead of raising
:exc:`NotImplementedError`.
.. class:: MetaPathFinder
......@@ -169,12 +173,19 @@ ABC hierarchy::
will be the value of :attr:`__path__` from the parent
package. If a loader cannot be found, ``None`` is returned.
.. versionchanged:: 3.4
Returns ``None`` when called instead of raising
:exc:`NotImplementedError`.
.. method:: invalidate_caches()
An optional method which, when called, should invalidate any internal
cache used by the finder. Used by :func:`importlib.invalidate_caches`
when invalidating the caches of all finders on :data:`sys.meta_path`.
.. versionchanged:: 3.4
Returns ``None`` when called instead of ``NotImplemented``.
.. class:: PathEntryFinder
......@@ -182,7 +193,7 @@ ABC hierarchy::
it bears some similarities to :class:`MetaPathFinder`, ``PathEntryFinder``
is meant for use only within the path-based import subsystem provided
by :class:`PathFinder`. This ABC is a subclass of :class:`Finder` for
compatibility.
compatibility reasons only.
.. versionadded:: 3.3
......@@ -194,9 +205,12 @@ ABC hierarchy::
package. The loader may be ``None`` while specifying ``portion`` to
signify the contribution of the file system locations to a namespace
package. An empty list can be used for ``portion`` to signify the loader
is not part of a package. If ``loader`` is ``None`` and ``portion`` is
the empty list then no loader or location for a namespace package were
found (i.e. failure to find anything for the module).
is not part of a namespace package. If ``loader`` is ``None`` and
``portion`` is the empty list then no loader or location for a namespace
package were found (i.e. failure to find anything for the module).
.. versionchanged:: 3.4
Returns ``(None, [])`` instead of raising :exc:`NotImplementedError`.
.. method:: find_module(fullname):
......@@ -249,21 +263,29 @@ ABC hierarchy::
- :attr:`__package__`
The parent package for the module/package. If the module is
top-level then it has a value of the empty string. The
:func:`importlib.util.set_package` decorator can handle the details
for :attr:`__package__`.
:func:`importlib.util.module_for_loader` decorator can handle the
details for :attr:`__package__`.
- :attr:`__loader__`
The loader used to load the module.
(This is not set by the built-in import machinery,
but it should be set whenever a :term:`loader` is used.)
The loader used to load the module. The
:func:`importlib.util.module_for_loader` decorator can handle the
details for :attr:`__package__`.
.. versionchanged:: 3.4
Raise :exc:`ImportError` when called instead of
:exc:`NotImplementedError`.
.. method:: module_repr(module)
An abstract method which when implemented calculates and returns the
given module's repr, as a string.
An optional method which when implemented calculates and returns the
given module's repr, as a string. The module type's default repr() will
use the result of this method as appropriate.
.. versionadded: 3.3
.. versionchanged:: 3.4
Made optional instead of an abstractmethod.
.. class:: ResourceLoader
......@@ -281,6 +303,9 @@ ABC hierarchy::
be found. The *path* is expected to be constructed using a module's
:attr:`__file__` attribute or an item from a package's :attr:`__path__`.
.. versionchanged:: 3.4
Raises :exc:`IOError` instead of :exc:`NotImplementedError`.
.. class:: InspectLoader
......@@ -297,6 +322,9 @@ ABC hierarchy::
.. index::
single: universal newlines; importlib.abc.InspectLoader.get_source method
.. versionchanged:: 3.4
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
.. method:: get_source(fullname)
An abstract method to return the source of a module. It is returned as
......@@ -305,12 +333,18 @@ ABC hierarchy::
if no source is available (e.g. a built-in module). Raises
:exc:`ImportError` if the loader cannot find the module specified.
.. versionchanged:: 3.4
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
.. method:: is_package(fullname)
An abstract method to return a true value if the module is a package, a
false value otherwise. :exc:`ImportError` is raised if the
:term:`loader` cannot find the module.
.. versionchanged:: 3.4
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
.. class:: ExecutionLoader
......@@ -328,6 +362,9 @@ ABC hierarchy::
the source file, regardless of whether a bytecode was used to load the
module.
.. versionchanged:: 3.4
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
.. class:: FileLoader(fullname, path)
......@@ -392,10 +429,13 @@ ABC hierarchy::
- ``'size'`` (optional): the size in bytes of the source code.
Any other keys in the dictionary are ignored, to allow for future
extensions.
extensions. If the path cannot be handled, :exc:`IOError` is raised.
.. versionadded:: 3.3
.. versionchanged:: 3.4
Raise :exc:`IOError` instead of :exc:`NotImplementedError`.
.. method:: path_mtime(path)
Optional abstract method which returns the modification time for the
......@@ -404,7 +444,10 @@ ABC hierarchy::
.. deprecated:: 3.3
This method is deprecated in favour of :meth:`path_stats`. You don't
have to implement it, but it is still available for compatibility
purposes.
purposes. Raise :exc:`IOError` if the path cannot be handled.
.. versionchanged:: 3.4
Raise :exc:`IOError` instead of :exc:`NotImplementedError`.
.. method:: set_data(path, data)
......@@ -415,6 +458,9 @@ ABC hierarchy::
When writing to the path fails because the path is read-only
(:attr:`errno.EACCES`), do not propagate the exception.
.. versionchanged:: 3.4
No longer raises :exc:`NotImplementedError` when called.
.. method:: source_to_code(data, path)
Create a code object from Python source.
......
......@@ -893,8 +893,10 @@ class SourceLoader(_LoaderBasics):
def path_mtime(self, path):
"""Optional method that returns the modification time (an int) for the
specified path, where path is a str.
Raises IOError when the path cannot be handled.
"""
raise NotImplementedError
raise IOError
def path_stats(self, path):
"""Optional method returning a metadata dict for the specified path
......@@ -905,6 +907,7 @@ class SourceLoader(_LoaderBasics):
- 'size' (optional) is the size in bytes of the source code.
Implementing this method allows the loader to read bytecode files.
Raises IOError when the path cannot be handled.
"""
return {'mtime': self.path_mtime(path)}
......@@ -922,9 +925,7 @@ class SourceLoader(_LoaderBasics):
"""Optional method which writes data (bytes) to a file path (a str).
Implementing this method allows for the writing of bytecode files.
"""
raise NotImplementedError
def get_source(self, fullname):
......@@ -973,7 +974,7 @@ class SourceLoader(_LoaderBasics):
else:
try:
st = self.path_stats(source_path)
except NotImplementedError:
except IOError:
pass
else:
source_mtime = int(st['mtime'])
......
......@@ -37,9 +37,8 @@ class Finder(metaclass=abc.ABCMeta):
def find_module(self, fullname, path=None):
"""An abstract method that should find a module.
The fullname is a str and the optional path is a str or None.
Returns a Loader object.
Returns a Loader object or None.
"""
raise NotImplementedError
class MetaPathFinder(Finder):
......@@ -49,16 +48,14 @@ class MetaPathFinder(Finder):
@abc.abstractmethod
def find_module(self, fullname, path):
"""Abstract method which, when implemented, should find a module.
The fullname is a str and the path is a str or None.
Returns a Loader object.
The fullname is a str and the path is a list of strings or None.
Returns a Loader object or None.
"""
raise NotImplementedError
def invalidate_caches(self):
"""An optional method for clearing the finder's cache, if any.
This method is used by importlib.invalidate_caches().
"""
return NotImplemented
_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
machinery.PathFinder, machinery.WindowsRegistryFinder)
......@@ -70,13 +67,14 @@ class PathEntryFinder(Finder):
@abc.abstractmethod
def find_loader(self, fullname):
"""Abstract method which, when implemented, returns a module loader.
"""Abstract method which, when implemented, returns a module loader or
a possible part of a namespace.
The fullname is a str. Returns a 2-tuple of (Loader, portion) where
portion is a sequence of file system locations contributing to part of
a namespace package. The sequence may be empty and the loader may be
None.
"""
raise NotImplementedError
return None, []
find_module = _bootstrap._find_module_shim
......@@ -84,25 +82,34 @@ class PathEntryFinder(Finder):
"""An optional method for clearing the finder's cache, if any.
This method is used by PathFinder.invalidate_caches().
"""
return NotImplemented
_register(PathEntryFinder, machinery.FileFinder)
class Loader(metaclass=abc.ABCMeta):
"""Abstract base class for import loaders."""
"""Abstract base class for import loaders.
The optional method module_repr(module) may be defined to provide a
repr for a module when appropriate (see PEP 420). The __repr__() method on
the module type will use the method as appropriate.
"""
@abc.abstractmethod
def load_module(self, fullname):
"""Abstract method which when implemented should load a module.
The fullname is a str."""
raise NotImplementedError
The fullname is a str.
ImportError is raised on failure.
"""
raise ImportError
@abc.abstractmethod
def module_repr(self, module):
"""Abstract method which when implemented calculates and returns the
given module's repr."""
"""Return a module's repr.
Used by the module type when implemented without raising an exception.
"""
raise NotImplementedError
......@@ -119,7 +126,7 @@ class ResourceLoader(Loader):
def get_data(self, path):
"""Abstract method which when implemented should return the bytes for
the specified path. The path must be a str."""
raise NotImplementedError
raise IOError
class InspectLoader(Loader):
......@@ -134,20 +141,29 @@ class InspectLoader(Loader):
@abc.abstractmethod
def is_package(self, fullname):
"""Abstract method which when implemented should return whether the
module is a package. The fullname is a str. Returns a bool."""
raise NotImplementedError
module is a package. The fullname is a str. Returns a bool.
Raises ImportError is the module cannot be found.
"""
raise ImportError
@abc.abstractmethod
def get_code(self, fullname):
"""Abstract method which when implemented should return the code object
for the module. The fullname is a str. Returns a types.CodeType."""
raise NotImplementedError
for the module. The fullname is a str. Returns a types.CodeType.
Raises ImportError if the module cannot be found.
"""
raise ImportError
@abc.abstractmethod
def get_source(self, fullname):
"""Abstract method which should return the source code for the
module. The fullname is a str. Returns a str."""
raise NotImplementedError
module. The fullname is a str. Returns a str.
Raises ImportError if the module cannot be found.
"""
raise ImportError
_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter,
machinery.ExtensionFileLoader)
......@@ -165,8 +181,11 @@ class ExecutionLoader(InspectLoader):
@abc.abstractmethod
def get_filename(self, fullname):
"""Abstract method which should return the value that __file__ is to be
set to."""
raise NotImplementedError
set to.
Raises ImportError if the module cannot be found.
"""
raise ImportError
class FileLoader(_bootstrap.FileLoader, ResourceLoader, ExecutionLoader):
......@@ -198,7 +217,7 @@ class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader):
def path_mtime(self, path):
"""Return the (int) modification time for the path (str)."""
if self.path_stats.__func__ is SourceLoader.path_stats:
raise NotImplementedError
raise IOError
return int(self.path_stats(path)['mtime'])
def path_stats(self, path):
......@@ -209,7 +228,7 @@ class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader):
- 'size' (optional) is the size in bytes of the source code.
"""
if self.path_mtime.__func__ is SourceLoader.path_mtime:
raise NotImplementedError
raise IOError
return {'mtime': self.path_mtime(path)}
def set_data(self, path, data):
......@@ -220,8 +239,6 @@ class SourceLoader(_bootstrap.SourceLoader, ResourceLoader, ExecutionLoader):
Any needed intermediary directories are to be created. If for some
reason the file cannot be written because of permissions, fail
silently.
"""
raise NotImplementedError
_register(SourceLoader, machinery.SourceFileLoader)
This diff is collapsed.
This diff is collapsed.
......@@ -30,6 +30,13 @@ Core and Builtins
Library
-------
- Issue #17093: Make the ABCs in importlib.abc provide default values or raise
reasonable exceptions for their methods to make them more amenable to super()
calls.
- Issue #17566: Make importlib.abc.Loader.module_repr() optional instead of an
abstractmethod and raising NotImplementedError so as to be ignored by default.
- Issue #17678: Remove the use of deprecated method in http/cookiejar.py.
Changing the usage of get_origin_req_host() to origin_req_host.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment