Skip to content

Commit 6ce3a67

Browse files
committed
switch logic to actually use origin, matching other code path
1 parent d0de86e commit 6ce3a67

File tree

3 files changed

+42
-37
lines changed

3 files changed

+42
-37
lines changed

Include/internal/pycore_moduleobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {
1111
extern void _PyModule_Clear(PyObject *);
1212
extern void _PyModule_ClearDict(PyObject *);
1313
extern int _PyModuleSpec_IsInitializing(PyObject *);
14+
extern int _PyModuleSpec_GetFileOrigin(PyObject *, PyObject **);
1415

1516
extern int _PyModule_IsExtension(PyObject *obj);
1617

Objects/moduleobject.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -824,15 +824,15 @@ _PyModuleSpec_IsUninitializedSubmodule(PyObject *spec, PyObject *name)
824824
return rc;
825825
}
826826

827-
static int
828-
_get_file_origin_from_spec(PyObject *spec, PyObject **p_origin)
827+
int
828+
_PyModuleSpec_GetFileOrigin(PyObject *spec, PyObject **p_origin)
829829
{
830830
PyObject *has_location = NULL;
831831
int rc = PyObject_GetOptionalAttr(spec, &_Py_ID(has_location), &has_location);
832832
if (rc <= 0) {
833833
return rc;
834834
}
835-
// If origin is not a location, or doesn't exist, or is not a str), we could consider falling
835+
// If origin is not a location, or doesn't exist, or is not a str, we could consider falling
836836
// back to module.__file__. But the cases in which module.__file__ is not __spec__.origin
837837
// are cases in which we probably shouldn't be guessing.
838838
rc = PyObject_IsTrue(has_location);
@@ -981,7 +981,7 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress)
981981
}
982982

983983
PyObject *origin = NULL;
984-
if (_get_file_origin_from_spec(spec, &origin) < 0) {
984+
if (_PyModuleSpec_GetFileOrigin(spec, &origin) < 0) {
985985
goto done;
986986
}
987987

Python/ceval.c

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,7 +2763,7 @@ PyObject *
27632763
_PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
27642764
{
27652765
PyObject *x;
2766-
PyObject *fullmodname, *mod_name, *origin, *mod_name_or_unknown, *errmsg;
2766+
PyObject *fullmodname, *mod_name, *origin, *mod_name_or_unknown, *errmsg, *spec;
27672767

27682768
if (PyObject_GetOptionalAttr(v, name, &x) != 0) {
27692769
return x;
@@ -2790,6 +2790,7 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
27902790
}
27912791
Py_DECREF(mod_name);
27922792
return x;
2793+
27932794
error:
27942795
if (mod_name == NULL) {
27952796
mod_name_or_unknown = PyUnicode_FromString("<unknown module name>");
@@ -2799,52 +2800,55 @@ _PyEval_ImportFrom(PyThreadState *tstate, PyObject *v, PyObject *name)
27992800
} else {
28002801
mod_name_or_unknown = mod_name;
28012802
}
2803+
// mod_name is no longer an owned reference
2804+
assert(mod_name == NULL || mod_name == mod_name_or_unknown);
28022805

28032806
origin = NULL;
2804-
if (PyModule_Check(v)) {
2805-
origin = PyModule_GetFilenameObject(v);
2806-
if (origin == NULL) {
2807-
if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
2808-
Py_DECREF(mod_name_or_unknown);
2809-
return NULL;
2810-
}
2811-
// module filename missing
2812-
_PyErr_Clear(tstate);
2813-
}
2807+
if (PyObject_GetOptionalAttr(v, &_Py_ID(__spec__), &spec) < 0) {
2808+
Py_DECREF(mod_name_or_unknown);
2809+
return NULL;
28142810
}
2815-
if (origin == NULL || !PyUnicode_Check(origin)) {
2816-
Py_CLEAR(origin);
2811+
if (spec == NULL) {
28172812
errmsg = PyUnicode_FromFormat(
28182813
"cannot import name %R from %R (unknown location)",
28192814
name, mod_name_or_unknown
28202815
);
2816+
goto done_with_errmsg;
2817+
}
2818+
if (_PyModuleSpec_GetFileOrigin(spec, &origin) < 0) {
2819+
goto done;
2820+
}
2821+
if (origin == NULL) {
2822+
errmsg = PyUnicode_FromFormat(
2823+
"cannot import name %R from %R (unknown location)",
2824+
name, mod_name_or_unknown
2825+
);
2826+
goto done_with_errmsg;
28212827
}
2822-
else {
2823-
PyObject *spec;
2824-
int rc = PyObject_GetOptionalAttr(v, &_Py_ID(__spec__), &spec);
2825-
if (rc > 0) {
2826-
rc = _PyModuleSpec_IsInitializing(spec);
2827-
Py_DECREF(spec);
2828-
}
2829-
if (rc < 0) {
2830-
Py_DECREF(mod_name_or_unknown);
2831-
Py_DECREF(origin);
2832-
return NULL;
2833-
}
2834-
const char *fmt =
2835-
rc ?
2836-
"cannot import name %R from partially initialized module %R "
2837-
"(most likely due to a circular import) (%S)" :
2838-
"cannot import name %R from %R (%S)";
28392828

2840-
errmsg = PyUnicode_FromFormat(fmt, name, mod_name_or_unknown, origin);
2829+
int rc = _PyModuleSpec_IsInitializing(spec);
2830+
if (rc < 0) {
2831+
Py_DECREF(mod_name_or_unknown);
2832+
Py_DECREF(origin);
2833+
return NULL;
28412834
}
2835+
const char *fmt =
2836+
rc ?
2837+
"cannot import name %R from partially initialized module %R "
2838+
"(most likely due to a circular import) (%S)" :
2839+
"cannot import name %R from %R (%S)";
2840+
2841+
errmsg = PyUnicode_FromFormat(fmt, name, mod_name_or_unknown, origin);
2842+
2843+
done_with_errmsg:
28422844
/* NULL checks for errmsg and mod_name done by PyErr_SetImportError. */
28432845
_PyErr_SetImportErrorWithNameFrom(errmsg, mod_name, origin, name);
2846+
Py_DECREF(errmsg);
28442847

2845-
Py_XDECREF(errmsg);
2846-
Py_DECREF(mod_name_or_unknown);
2848+
done:
28472849
Py_XDECREF(origin);
2850+
Py_XDECREF(spec);
2851+
Py_DECREF(mod_name_or_unknown);
28482852
return NULL;
28492853
}
28502854

0 commit comments

Comments
 (0)