cpython: 3a50025f1900 (original) (raw)
Mercurial > cpython
changeset 84109:3a50025f1900
Issue #15767: Touch up ModuleNotFoundError usage by import. Forgot to raise ModuleNotFoundError when None is found in sys.modules. This led to introducing the C function PyErr_SetImportErrorSubclass() to make setting ModuleNotFoundError easier. Also updated the reference docs to mention ModuleNotFoundError appropriately. Updated the docs for ModuleNotFoundError to mention the None in sys.modules case. Lastly, it was noticed that PyErr_SetImportError() was not setting an exception when returning None in one case. That issue is now fixed. [#15767]
Brett Cannon brett@python.org | |
---|---|
date | Wed, 12 Jun 2013 23:29:18 -0400 |
parents | 05f7883ee92d |
children | c6c0faaf65d7 |
files | Doc/c-api/exceptions.rst Doc/library/exceptions.rst Doc/reference/import.rst Doc/whatsnew/3.4.rst Include/pyerrors.h Lib/importlib/_bootstrap.py Misc/NEWS Python/errors.c Python/import.c Python/importlib.h |
diffstat | 10 files changed, 52 insertions(+), 14 deletions(-)[+] [-] Doc/c-api/exceptions.rst 7 Doc/library/exceptions.rst 3 Doc/reference/import.rst 12 Doc/whatsnew/3.4.rst 3 Include/pyerrors.h 3 Lib/importlib/_bootstrap.py 2 Misc/NEWS 4 Python/errors.c 25 Python/import.c 3 Python/importlib.h 4 |
line wrap: on
line diff
--- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -292,6 +292,13 @@ in various ways. There is a separate er .. versionadded:: 3.3 +.. c:function:: PyObject* PyErr_SetImportErrorSubclass(PyObject *msg, PyObject *name, PyObject *path) +
- Much like :c:func:
PyErr_SetImportError
but this function allows for - specifying a subclass of :exc:
ImportError
to raise. + - .. versionadded:: 3.4 +
.. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset)
--- a/Doc/library/exceptions.rst
+++ b/Doc/library/exceptions.rst
@@ -185,7 +185,8 @@ The following exceptions are the excepti
A subclass of :exc:ImportError
which is raised by :keyword:import
when a
module could not be located. This includes from ... import
statements as
the specific attribute being requested cannot be known a priori to be a module
- or some other type of object. It is also raised when
None
is found in - :data:
sys.modules
. .. versionadded:: 3.4
--- a/Doc/reference/import.rst
+++ b/Doc/reference/import.rst
@@ -37,7 +37,7 @@ use the standard import system.
When a module is first imported, Python searches for the module and if found,
it creates a module object [#fnmo]_, initializing it. If the named module
-cannot be found, an :exc:ImportError
is raised. Python implements various
+cannot be found, an :exc:ModuleNotFoundError
is raised. Python implements various
strategies to search for the named module when the import machinery is
invoked. These strategies can be modified and extended by using various hooks
described in the sections below.
@@ -168,7 +168,7 @@ arguments to the :keyword:import
state
This name will be used in various phases of the import search, and it may be
the dotted path to a submodule, e.g. foo.bar.baz
. In this case, Python
first tries to import foo
, then foo.bar
, and finally foo.bar.baz
.
-If any of the intermediate imports fail, an :exc:ImportError
is raised.
+If any of the intermediate imports fail, an :exc:ModuleNotFoundError
is raised.
The module cache
@@ -187,7 +187,7 @@ object.
During import, the module name is looked up in :data:sys.modules
and if
present, the associated value is the module satisfying the import, and the
process completes. However, if the value is None
, then an
-:exc:ImportError
is raised. If the module name is missing, Python will
+:exc:ModuleNotFoundError
is raised. If the module name is missing, Python will
continue searching for the module.
:data:sys.modules
is writable. Deleting a key may not destroy the
@@ -195,7 +195,7 @@ associated module (as other modules may
but it will invalidate the cache entry for the named module, causing
Python to search anew for the named module upon its next
import. The key can also be assigned to None
, forcing the next import
-of the module to result in an :exc:ImportError
.
+of the module to result in an :exc:ModuleNotFoundError
.
Beware though, as if you keep a reference to the module object,
invalidate its cache entry in :data:sys.modules
, and then re-import the
@@ -284,7 +284,7 @@ handle the named module or not.
If the meta path finder knows how to handle the named module, it returns a
loader object. If it cannot handle the named module, it returns None
. If
:data:sys.meta_path
processing reaches the end of its list without returning
-a loader, then an :exc:ImportError
is raised. Any other exceptions raised
+a loader, then an :exc:ModuleNotFoundError
is raised. Any other exceptions raised
are simply propagated up, aborting the import process.
The :meth:find_module()
method of meta path finders is called with two
@@ -647,7 +647,7 @@ import statements within that module.
To selectively prevent import of some modules from a hook early on the
meta path (rather than disabling the standard import system entirely),
-it is sufficient to raise :exc:ImportError
directly from
+it is sufficient to raise :exc:ModuleNotFoundError
directly from
:meth:find_module
instead of returning None
. The latter indicates
that the meta path search should continue. while raising an exception
terminates it immediately.
--- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -269,3 +269,6 @@ that may require changes to your code.
- Frozen packages no longer set
__path__
to a list containg the package name but an empty list instead. Determing if a module is a package should be done usinghasattr(module, '__path__')
. + +* :c:func:PyErr_SetImportError
now sets :exc:TypeError
when its msg
--- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -268,6 +268,9 @@ PyAPI_FUNC(PyObject *) PyErr_SetExcFromW PyAPI_FUNC(PyObject *) PyErr_SetExcWithArgsKwargs(PyObject *, PyObject *, PyObject *); + +PyAPI_FUNC(PyObject *) PyErr_SetImportErrorSubclass(PyObject *, PyObject *,
PyAPI_FUNC(PyObject *) PyErr_SetImportError(PyObject *, PyObject *, PyObject *);
--- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1614,7 +1614,7 @@ def _gcd_import(name, package=None, leve _imp.release_lock() message = ("import of {} halted; " "None in sys.modules".format(name))
raise ImportError(message, name=name)[](#l6.7)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -443,6 +443,10 @@ Tests C-API ----- +- Issue #15767: Added PyErr_SetImportErrorSubclass(). + +- PyErr_SetImportError() now sets TypeError when its msg argument is set. +
- Issue #9369: The types of
char*
arguments of PyObject_CallFunction() and PyObject_CallMethod() now changed toconst char*
. Based on patches by Jörg Müller and Lars Buitinck.
--- a/Python/errors.c +++ b/Python/errors.c @@ -619,12 +619,25 @@ PyObject PyErr_SetFromWindowsErrWithUni #endif / MS_WINDOWS */ PyObject * -PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) +PyErr_SetImportErrorSubclass(PyObject *exception, PyObject *msg,
- issubclass = PyObject_IsSubclass(exception, PyExc_ImportError);
- if (issubclass < 0) {
return NULL;[](#l8.17)
- }
- else if (!issubclass) {
PyErr_SetString(PyExc_TypeError, "expected a subclass of ImportError");[](#l8.20) return NULL;[](#l8.21)
- }
- if (msg == NULL) {
PyErr_SetString(PyExc_TypeError, "expected a message argument");[](#l8.25)
return NULL;[](#l8.26)
- }
args = PyTuple_New(1); if (args == NULL) @@ -649,7 +662,7 @@ PyErr_SetImportError(PyObject *msg, PyOb PyDict_SetItemString(kwargs, "name", name); PyDict_SetItemString(kwargs, "path", path);
- error = PyObject_Call(exception, args, kwargs); if (error != NULL) { PyErr_SetObject((PyObject *)Py_TYPE(error), error); Py_DECREF(error);
@@ -661,6 +674,12 @@ PyErr_SetImportError(PyObject *msg, PyOb return NULL; } +PyObject * +PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) +{
+} + void _PyErr_BadInternalCall(const char *filename, int lineno) {
--- a/Python/import.c +++ b/Python/import.c @@ -1436,7 +1436,8 @@ PyImport_ImportModuleLevelObject(PyObjec PyObject *msg = PyUnicode_FromFormat("import of %R halted; " "None in sys.modules", abs_name); if (msg != NULL) {
PyErr_SetImportError(msg, abs_name, NULL);[](#l9.7)
PyErr_SetImportErrorSubclass(PyExc_ModuleNotFoundError, msg,[](#l9.8)
abs_name, NULL);[](#l9.9) Py_DECREF(msg);[](#l9.10) }[](#l9.11) mod = NULL;[](#l9.12)
--- a/Python/importlib.h +++ b/Python/importlib.h @@ -3239,8 +3239,8 @@ const unsigned char _Py_M__importlib[] = 0,114,64,1,0,0,114,59,1,0,0,114,96,0,0,0, 114,56,1,0,0,114,7,0,0,0,114,145,0,0,0,114, 69,1,0,0,244,11,0,0,0,95,103,99,100,95,105,109,