mirror of
https://github.com/python/cpython.git
synced 2025-10-17 20:28:43 +00:00
Issue #25791: Warn when __package__ != __spec__.parent.
In a previous change, __spec__.parent was prioritized over __package__. That is a backwards-compatibility break, but we do eventually want __spec__ to be the ground truth for module details. So this change reverts the change in semantics and instead raises an ImportWarning when __package__ != __spec__.parent to give people time to adjust to using spec objects.
This commit is contained in:
parent
52c854a838
commit
849113af6b
8 changed files with 184 additions and 121 deletions
|
@ -1415,60 +1415,79 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
|
|||
goto error;
|
||||
}
|
||||
else if (level > 0) {
|
||||
package = _PyDict_GetItemId(globals, &PyId___package__);
|
||||
spec = _PyDict_GetItemId(globals, &PyId___spec__);
|
||||
if (spec != NULL) {
|
||||
package = PyObject_GetAttrString(spec, "parent");
|
||||
}
|
||||
|
||||
if (package != NULL && package != Py_None) {
|
||||
Py_INCREF(package);
|
||||
if (!PyUnicode_Check(package)) {
|
||||
PyErr_SetString(PyExc_TypeError, "package must be a string");
|
||||
goto error;
|
||||
}
|
||||
else if (spec != NULL) {
|
||||
int equal;
|
||||
PyObject *parent = PyObject_GetAttrString(spec, "parent");
|
||||
if (parent == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
equal = PyObject_RichCompareBool(package, parent, Py_EQ);
|
||||
Py_DECREF(parent);
|
||||
if (equal < 0) {
|
||||
goto error;
|
||||
}
|
||||
else if (equal == 0) {
|
||||
if (PyErr_WarnEx(PyExc_ImportWarning,
|
||||
"__package__ != __spec__.parent", 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (spec != NULL) {
|
||||
package = PyObject_GetAttrString(spec, "parent");
|
||||
if (package == NULL) {
|
||||
goto error;
|
||||
}
|
||||
else if (!PyUnicode_Check(package)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"__spec__.parent must be a string");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
package = _PyDict_GetItemId(globals, &PyId___package__);
|
||||
if (package != NULL && package != Py_None) {
|
||||
Py_INCREF(package);
|
||||
if (!PyUnicode_Check(package)) {
|
||||
PyErr_SetString(PyExc_TypeError, "package must be a string");
|
||||
goto error;
|
||||
}
|
||||
if (PyErr_WarnEx(PyExc_ImportWarning,
|
||||
"can't resolve package from __spec__ or __package__, "
|
||||
"falling back on __name__ and __path__", 1) < 0) {
|
||||
goto error;
|
||||
}
|
||||
else {
|
||||
if (PyErr_WarnEx(PyExc_ImportWarning,
|
||||
"can't resolve package from __spec__ or __package__, "
|
||||
"falling back on __name__ and __path__", 1) < 0) {
|
||||
|
||||
package = _PyDict_GetItemId(globals, &PyId___name__);
|
||||
if (package == NULL) {
|
||||
PyErr_SetString(PyExc_KeyError, "'__name__' not in globals");
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_INCREF(package);
|
||||
if (!PyUnicode_Check(package)) {
|
||||
PyErr_SetString(PyExc_TypeError, "__name__ must be a string");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) {
|
||||
PyObject *partition = NULL;
|
||||
PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot);
|
||||
if (borrowed_dot == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
package = _PyDict_GetItemId(globals, &PyId___name__);
|
||||
if (package == NULL) {
|
||||
PyErr_SetString(PyExc_KeyError, "'__name__' not in globals");
|
||||
partition = PyUnicode_RPartition(package, borrowed_dot);
|
||||
Py_DECREF(package);
|
||||
if (partition == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
package = PyTuple_GET_ITEM(partition, 0);
|
||||
Py_INCREF(package);
|
||||
if (!PyUnicode_Check(package)) {
|
||||
PyErr_SetString(PyExc_TypeError, "__name__ must be a string");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) {
|
||||
PyObject *partition = NULL;
|
||||
PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot);
|
||||
if (borrowed_dot == NULL) {
|
||||
goto error;
|
||||
}
|
||||
partition = PyUnicode_RPartition(package, borrowed_dot);
|
||||
Py_DECREF(package);
|
||||
if (partition == NULL) {
|
||||
goto error;
|
||||
}
|
||||
package = PyTuple_GET_ITEM(partition, 0);
|
||||
Py_INCREF(package);
|
||||
Py_DECREF(partition);
|
||||
}
|
||||
Py_DECREF(partition);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue