Skip to content

Commit 09b86d1

Browse files
committed
Fix #14600. Correct reference handling and naming of ImportError convenience function
1 parent fba807a commit 09b86d1

File tree

5 files changed

+31
-53
lines changed

5 files changed

+31
-53
lines changed

Doc/c-api/exceptions.rst

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -229,27 +229,12 @@ in various ways. There is a separate error indicator for each thread.
229229
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional
230230
parameter specifying the exception type to be raised. Availability: Windows.
231231
232-
.. c:function:: PyObject* PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs)
233-
234-
This is a convenience function to set an *exc* with the given *args* and
235-
*kwargs* values. If *args* is ``NULL``, an empty :func:`tuple` will be
236-
created when *exc* is created via :c:func:`PyObject_Call`.
237-
238-
.. versionadded:: 3.3
239-
240-
.. c:function:: PyObject* PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name)
241-
242-
This is a convenience function to raise :exc:`ImportError`. *msg* will be
243-
set as the exception's message string, and *name* will be set as the
244-
:exc:`ImportError`'s ``name`` attribute.
245-
246-
.. versionadded:: 3.3
247-
248-
.. c:function:: PyObject* PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, PyObject *name, PyObject *path)
232+
.. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
249233
250234
This is a convenience function to raise :exc:`ImportError`. *msg* will be
251-
set as the exception's message string. Both *name* and *path* will be set
252-
as the :exc:`ImportError`'s respective ``name`` and ``path`` attributes.
235+
set as the exception's message string. *name* and *path*, both of which can
236+
be ``NULL``, will be set as the :exc:`ImportError`'s respective ``name``
237+
and ``path`` attributes.
253238
254239
.. versionadded:: 3.3
255240

Include/pyerrors.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,8 @@ PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int);
265265

266266
PyAPI_FUNC(PyObject *) PyErr_SetExcWithArgsKwargs(PyObject *, PyObject *,
267267
PyObject *);
268-
PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithNameAndPath(PyObject *,
269-
PyObject *, PyObject *);
270-
PyAPI_FUNC(PyObject *) PyErr_SetFromImportErrorWithName(PyObject *, PyObject *);
268+
PyAPI_FUNC(PyObject *) PyErr_SetImportError(PyObject *, PyObject *,
269+
PyObject *);
271270

272271
/* Export the old function so that the existing API remains available: */
273272
PyAPI_FUNC(void) PyErr_BadInternalCall(void);

Python/dynload_win.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,9 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname,
254254
theLength));
255255
}
256256
if (message != NULL) {
257-
PyErr_SetFromImportErrorWithNameAndPath(message,
258-
PyUnicode_FromString(shortname),
259-
pathname);
257+
PyErr_SetImportError(message, PyUnicode_FromString(shortname),
258+
pathname);
259+
Py_DECREF(message);
260260
}
261261
return NULL;
262262
} else {

Python/errors.c

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -586,50 +586,43 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
586586
#endif /* MS_WINDOWS */
587587

588588
PyObject *
589-
PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs)
589+
PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
590590
{
591-
PyObject *val;
591+
PyObject *args, *kwargs, *error;
592592

593-
/* args must at least be an empty tuple */
593+
args = PyTuple_New(1);
594594
if (args == NULL)
595-
args = PyTuple_New(0);
596-
597-
val = PyObject_Call(exc, args, kwargs);
598-
if (val != NULL) {
599-
PyErr_SetObject((PyObject *) Py_TYPE(val), val);
600-
Py_DECREF(val);
601-
}
595+
return NULL;
602596

603-
return NULL;
604-
}
597+
kwargs = PyDict_New();
598+
if (args == NULL)
599+
return NULL;
605600

606-
PyObject *
607-
PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg,
608-
PyObject *name, PyObject *path)
609-
{
610-
PyObject *args = PyTuple_New(1);
611-
PyObject *kwargs = PyDict_New();
612-
PyObject *result;
601+
if (name == NULL)
602+
name = Py_None;
613603

614604
if (path == NULL)
615605
path = Py_None;
616606

607+
Py_INCREF(msg);
617608
PyTuple_SetItem(args, 0, msg);
618609
PyDict_SetItemString(kwargs, "name", name);
619610
PyDict_SetItemString(kwargs, "path", path);
620611

621-
result = PyErr_SetExcWithArgsKwargs(PyExc_ImportError, args, kwargs);
612+
/* args must at least be an empty tuple */
613+
if (args == NULL)
614+
args = PyTuple_New(0);
615+
616+
error = PyObject_Call(PyExc_ImportError, args, kwargs);
617+
if (error!= NULL) {
618+
PyErr_SetObject((PyObject *) Py_TYPE(error), error);
619+
Py_DECREF(error);
620+
}
622621

623622
Py_DECREF(args);
624623
Py_DECREF(kwargs);
625624

626-
return result;
627-
}
628-
629-
PyObject *
630-
PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name)
631-
{
632-
return PyErr_SetFromImportErrorWithNameAndPath(msg, name, NULL);
625+
return NULL;
633626
}
634627

635628
void

Python/import.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2460,7 +2460,8 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
24602460
PyObject *msg = PyUnicode_FromFormat("import of %R halted; "
24612461
"None in sys.modules", abs_name);
24622462
if (msg != NULL) {
2463-
PyErr_SetFromImportErrorWithName(msg, abs_name);
2463+
PyErr_SetImportError(msg, abs_name, NULL);
2464+
Py_DECREF(msg);
24642465
}
24652466
mod = NULL;
24662467
goto error_with_unlock;

0 commit comments

Comments
 (0)