summaryrefslogtreecommitdiff
path: root/Python/import.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/import.c')
-rw-r--r--Python/import.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/Python/import.c b/Python/import.c
index 0b843dafd3..22f94f5f18 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -320,7 +320,7 @@ PyImport_GetModuleDict(void)
/* List of names to clear in sys */
-static char* sys_deletes[] = {
+static const char * const sys_deletes[] = {
"path", "argv", "ps1", "ps2",
"last_type", "last_value", "last_traceback",
"path_hooks", "path_importer_cache", "meta_path",
@@ -330,7 +330,7 @@ static char* sys_deletes[] = {
NULL
};
-static char* sys_files[] = {
+static const char * const sys_files[] = {
"stdin", "__stdin__",
"stdout", "__stdout__",
"stderr", "__stderr__",
@@ -347,7 +347,7 @@ PyImport_Cleanup(void)
PyInterpreterState *interp = PyThreadState_GET()->interp;
PyObject *modules = interp->modules;
PyObject *weaklist = NULL;
- char **p;
+ const char * const *p;
if (modules == NULL)
return; /* Already done */
@@ -883,10 +883,8 @@ update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
if (PyUnicode_Compare(co->co_filename, oldname))
return;
- tmp = co->co_filename;
- co->co_filename = newname;
- Py_INCREF(co->co_filename);
- Py_DECREF(tmp);
+ Py_INCREF(newname);
+ Py_SETREF(co->co_filename, newname);
constants = co->co_consts;
n = PyTuple_GET_SIZE(constants);
@@ -1331,10 +1329,8 @@ remove_importlib_frames(void)
(always_trim ||
PyUnicode_CompareWithASCIIString(code->co_name,
remove_frames) == 0)) {
- PyObject *tmp = *outer_link;
- *outer_link = next;
Py_XINCREF(next);
- Py_DECREF(tmp);
+ Py_SETREF(*outer_link, next);
prev_link = outer_link;
}
else {
@@ -1367,6 +1363,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;
@@ -1423,23 +1420,63 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
}
else if (level > 0) {
package = _PyDict_GetItemId(globals, &PyId___package__);
+ spec = _PyDict_GetItemId(globals, &PyId___spec__);
+
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 && spec != Py_None) {
+ 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 && spec != Py_None) {
+ 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 {
+ if (PyErr_WarnEx(PyExc_ImportWarning,
+ "can't resolve package from __spec__ or __package__, "
+ "falling back on __name__ and __path__", 1) < 0) {
+ goto error;
+ }
+
package = _PyDict_GetItemId(globals, &PyId___name__);
if (package == NULL) {
PyErr_SetString(PyExc_KeyError, "'__name__' not in globals");
goto error;
}
- else if (!PyUnicode_Check(package)) {
+
+ Py_INCREF(package);
+ if (!PyUnicode_Check(package)) {
PyErr_SetString(PyExc_TypeError, "__name__ must be a string");
+ goto error;
}
- Py_INCREF(package);
if (_PyDict_GetItemId(globals, &PyId___path__) == NULL) {
PyObject *partition = NULL;
@@ -1458,7 +1495,12 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,
}
}
- if (PyDict_GetItem(interp->modules, package) == NULL) {
+ if (PyUnicode_CompareWithASCIIString(package, "") == 0) {
+ PyErr_SetString(PyExc_ImportError,
+ "attempted relative import with no known parent package");
+ goto error;
+ }
+ else if (PyDict_GetItem(interp->modules, package) == NULL) {
PyErr_Format(PyExc_SystemError,
"Parent module %R not loaded, cannot perform relative "
"import", package);