diff options
author | Brett Cannon <brett@python.org> | 2016-01-15 21:33:03 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2016-01-15 21:33:03 (GMT) |
commit | 63b8505281f9c26f7304b3e00d658b429b862d5b (patch) | |
tree | 07a4d20ed327d8493aa7105bec9ca1d598cc6b7c /Python/import.c | |
parent | 43cfd8240c274b2f4cf0588f3defae83e7379a55 (diff) | |
download | cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.zip cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.tar.gz cpython-63b8505281f9c26f7304b3e00d658b429b862d5b.tar.bz2 |
Issue #25791: Raise an ImportWarning when __spec__ or __package__ are
not defined for a relative import.
This is the start of work to try and clean up import semantics to rely
more on a module's spec than on the myriad attributes that get set on
a module. Thanks to Rose Ames for the patch.
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/Python/import.c b/Python/import.c index 325b936..c1071c0 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1359,6 +1359,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, PyObject *final_mod = NULL; PyObject *mod = NULL; PyObject *package = NULL; + PyObject *spec = NULL; PyObject *globals = NULL; PyObject *fromlist = NULL; PyInterpreterState *interp = PyThreadState_GET()->interp; @@ -1414,39 +1415,60 @@ 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"); + PyErr_SetString(PyExc_TypeError, + "__spec__.parent must be a string"); goto error; } } else { - package = _PyDict_GetItemId(globals, &PyId___name__); - if (package == NULL) { - PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); - goto error; - } - else if (!PyUnicode_Check(package)) { - PyErr_SetString(PyExc_TypeError, "__name__ must be a string"); + 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; + } } - Py_INCREF(package); - - if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) { - PyObject *partition = NULL; - PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); - if (borrowed_dot == NULL) { + else { + if (PyErr_WarnEx(PyExc_ImportWarning, + "can't resolve package from __spec__ or __package__, " + "falling back on __name__ and __path__", 1) < 0) { goto error; } - partition = PyUnicode_RPartition(package, borrowed_dot); - Py_DECREF(package); - if (partition == NULL) { + + package = _PyDict_GetItemId(globals, &PyId___name__); + if (package == NULL) { + PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); goto error; } - package = PyTuple_GET_ITEM(partition, 0); + Py_INCREF(package); - Py_DECREF(partition); + 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); + } } } |