summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/exceptions.rst2
-rw-r--r--Doc/library/exceptions.rst13
-rw-r--r--Include/pyerrors.h1
-rw-r--r--Lib/_compat_pickle.py7
-rw-r--r--Lib/test/exception_hierarchy.txt1
-rw-r--r--Lib/test/test_pickle.py8
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/exceptions.c9
8 files changed, 42 insertions, 2 deletions
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 226b619..5644410 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -782,6 +782,8 @@ the variables:
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_ImportError` | :exc:`ImportError` | |
+-----------------------------------------+---------------------------------+----------+
+| :c:data:`PyExc_ModuleNotFoundError` | :exc:`ModuleNotFoundError` | |
++-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_IndexError` | :exc:`IndexError` | |
+-----------------------------------------+---------------------------------+----------+
| :c:data:`PyExc_InterruptedError` | :exc:`InterruptedError` | |
diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst
index 1747efe..a428f51 100644
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -170,8 +170,9 @@ The following exceptions are the exceptions that are usually raised.
.. exception:: ImportError
- Raised when an :keyword:`import` statement fails to find the module definition
- or when a ``from ... import`` fails to find a name that is to be imported.
+ Raised when the :keyword:`import` statement has troubles trying to
+ load a module. Also raised when the "from list" in ``from ... import``
+ has a name that cannot be found.
The :attr:`name` and :attr:`path` attributes can be set using keyword-only
arguments to the constructor. When set they represent the name of the module
@@ -181,6 +182,14 @@ The following exceptions are the exceptions that are usually raised.
.. versionchanged:: 3.3
Added the :attr:`name` and :attr:`path` attributes.
+.. exception:: ModuleNotFoundError
+
+ A subclass of :exc:`ImportError` which is raised by :keyword:`import`
+ when a module could not be located. It is also raised when ``None``
+ is found in :data:`sys.modules`.
+
+ .. versionadded:: 3.6
+
.. exception:: IndexError
diff --git a/Include/pyerrors.h b/Include/pyerrors.h
index 35aedb7..6bc3ca7 100644
--- a/Include/pyerrors.h
+++ b/Include/pyerrors.h
@@ -160,6 +160,7 @@ PyAPI_DATA(PyObject *) PyExc_EOFError;
PyAPI_DATA(PyObject *) PyExc_FloatingPointError;
PyAPI_DATA(PyObject *) PyExc_OSError;
PyAPI_DATA(PyObject *) PyExc_ImportError;
+PyAPI_DATA(PyObject *) PyExc_ModuleNotFoundError;
PyAPI_DATA(PyObject *) PyExc_IndexError;
PyAPI_DATA(PyObject *) PyExc_KeyError;
PyAPI_DATA(PyObject *) PyExc_KeyboardInterrupt;
diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py
index c0e0443..f68496a 100644
--- a/Lib/_compat_pickle.py
+++ b/Lib/_compat_pickle.py
@@ -242,3 +242,10 @@ PYTHON3_OSERROR_EXCEPTIONS = (
for excname in PYTHON3_OSERROR_EXCEPTIONS:
REVERSE_NAME_MAPPING[('builtins', excname)] = ('exceptions', 'OSError')
+
+PYTHON3_IMPORTERROR_EXCEPTIONS = (
+ 'ModuleNotFoundError',
+)
+
+for excname in PYTHON3_IMPORTERROR_EXCEPTIONS:
+ REVERSE_NAME_MAPPING[('builtins', excname)] = ('exceptions', 'ImportError')
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
index 0513765..7333b2a 100644
--- a/Lib/test/exception_hierarchy.txt
+++ b/Lib/test/exception_hierarchy.txt
@@ -14,6 +14,7 @@ BaseException
+-- BufferError
+-- EOFError
+-- ImportError
+ +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
index 05203e5..e6c5d08 100644
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -335,6 +335,9 @@ class CompatPickleTests(unittest.TestCase):
if (module2, name2) == ('exceptions', 'OSError'):
attr = getattribute(module3, name3)
self.assertTrue(issubclass(attr, OSError))
+ elif (module2, name2) == ('exceptions', 'ImportError'):
+ attr = getattribute(module3, name3)
+ self.assertTrue(issubclass(attr, ImportError))
else:
module, name = mapping(module2, name2)
if module3[:1] != '_':
@@ -401,6 +404,11 @@ class CompatPickleTests(unittest.TestCase):
if exc is not OSError and issubclass(exc, OSError):
self.assertEqual(reverse_mapping('builtins', name),
('exceptions', 'OSError'))
+ elif exc is not ImportError and issubclass(exc, ImportError):
+ self.assertEqual(reverse_mapping('builtins', name),
+ ('exceptions', 'ImportError'))
+ self.assertEqual(mapping('exceptions', name),
+ ('exceptions', name))
else:
self.assertEqual(reverse_mapping('builtins', name),
('exceptions', name))
diff --git a/Misc/NEWS b/Misc/NEWS
index edfff7b..2692277 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -8043,6 +8043,9 @@ Core and Builtins
- Issue #18137: Detect integer overflow on precision in float.__format__()
and complex.__format__().
+- Issue #15767: Introduce ModuleNotFoundError which is raised when a module
+ could not be found.
+
- Issue #18183: Fix various unicode operations on strings with large unicode
codepoints.
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 336c32c..6fb5eb7 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -706,6 +706,13 @@ ComplexExtendsException(PyExc_Exception, ImportError,
"module.");
/*
+ * ModuleNotFoundError extends ImportError
+ */
+
+MiddlingExtendsException(PyExc_ImportError, ModuleNotFoundError, ImportError,
+ "Module not found.");
+
+/*
* OSError extends Exception
*/
@@ -2469,6 +2476,7 @@ _PyExc_Init(PyObject *bltinmod)
PRE_INIT(SystemExit)
PRE_INIT(KeyboardInterrupt)
PRE_INIT(ImportError)
+ PRE_INIT(ModuleNotFoundError)
PRE_INIT(OSError)
PRE_INIT(EOFError)
PRE_INIT(RuntimeError)
@@ -2541,6 +2549,7 @@ _PyExc_Init(PyObject *bltinmod)
POST_INIT(SystemExit)
POST_INIT(KeyboardInterrupt)
POST_INIT(ImportError)
+ POST_INIT(ModuleNotFoundError)
POST_INIT(OSError)
INIT_ALIAS(EnvironmentError, OSError)
INIT_ALIAS(IOError, OSError)