diff options
Diffstat (limited to 'Python/import.c')
| -rw-r--r-- | Python/import.c | 423 | 
1 files changed, 203 insertions, 220 deletions
| diff --git a/Python/import.c b/Python/import.c index 7e947ec..dfdd940 100644 --- a/Python/import.c +++ b/Python/import.c @@ -38,14 +38,6 @@ module _imp  #include "clinic/import.c.h" -/*[python input] -class fs_unicode_converter(CConverter): -    type = 'PyObject *' -    converter = 'PyUnicode_FSDecoder' - -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=9d6786230166006e]*/ -  /* Initialize things */  void @@ -320,7 +312,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 +322,7 @@ static char* sys_deletes[] = {      NULL  }; -static char* sys_files[] = { +static const char * const sys_files[] = {      "stdin", "__stdin__",      "stdout", "__stdout__",      "stderr", "__stderr__", @@ -347,7 +339,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 +875,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_XSETREF(co->co_filename, newname);      constants = co->co_consts;      n = PyTuple_GET_SIZE(constants); @@ -1087,6 +1077,10 @@ _imp_create_builtin(PyObject *module, PyObject *spec)              } else {                  /* Remember pointer to module init function. */                  def = PyModule_GetDef(mod); +                if (def == NULL) { +                    Py_DECREF(name); +                    return NULL; +                }                  def->m_base.m_init = p->initfunc;                  if (_PyImport_FixupExtensionObject(mod, name, name) < 0) {                      Py_DECREF(name); @@ -1332,10 +1326,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_XSETREF(*outer_link, next);              prev_link = outer_link;          }          else { @@ -1348,61 +1340,170 @@ done:  } -PyObject * -PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals, -                                 PyObject *locals, PyObject *given_fromlist, -                                 int level) +static PyObject * +resolve_name(PyObject *name, PyObject *globals, int level)  { -    _Py_IDENTIFIER(__import__);      _Py_IDENTIFIER(__spec__); -    _Py_IDENTIFIER(_initializing);      _Py_IDENTIFIER(__package__);      _Py_IDENTIFIER(__path__);      _Py_IDENTIFIER(__name__); -    _Py_IDENTIFIER(_find_and_load); -    _Py_IDENTIFIER(_handle_fromlist); -    _Py_IDENTIFIER(_lock_unlock_module); -    _Py_static_string(single_dot, "."); -    PyObject *abs_name = NULL; -    PyObject *builtins_import = NULL; -    PyObject *final_mod = NULL; -    PyObject *mod = NULL; +    _Py_IDENTIFIER(parent); +    PyObject *abs_name;      PyObject *package = NULL; -    PyObject *globals = NULL; -    PyObject *fromlist = NULL; +    PyObject *spec;      PyInterpreterState *interp = PyThreadState_GET()->interp; -    int has_from; +    Py_ssize_t last_dot; +    PyObject *base; +    int level_up; -    /* Make sure to use default values so as to not have -       PyObject_CallMethodObjArgs() truncate the parameter list because of a -       NULL argument. */ -    if (given_globals == NULL) { -        globals = PyDict_New(); -        if (globals == NULL) { +    if (globals == NULL) { +        PyErr_SetString(PyExc_KeyError, "'__name__' not in globals"); +        goto error; +    } +    if (!PyDict_Check(globals)) { +        PyErr_SetString(PyExc_TypeError, "globals must be a dict"); +        goto error; +    } +    package = _PyDict_GetItemId(globals, &PyId___package__); +    if (package == Py_None) { +        package = NULL; +    } +    spec = _PyDict_GetItemId(globals, &PyId___spec__); + +    if (package != NULL) { +        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_GetAttrId(spec, &PyId_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_GetAttrId(spec, &PyId_parent); +        if (package == NULL) { +            goto error; +        } +        else if (!PyUnicode_Check(package)) { +            PyErr_SetString(PyExc_TypeError, +                    "__spec__.parent must be a string");              goto error;          }      }      else { -        /* Only have to care what given_globals is if it will be used -           for something. */ -        if (level > 0 && !PyDict_Check(given_globals)) { -            PyErr_SetString(PyExc_TypeError, "globals must be a dict"); +        if (PyErr_WarnEx(PyExc_ImportWarning, +                    "can't resolve package from __spec__ or __package__, " +                    "falling back on __name__ and __path__", 1) < 0) {              goto error;          } -        globals = given_globals; -        Py_INCREF(globals); + +        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) { +            Py_ssize_t dot; + +            if (PyUnicode_READY(package) < 0) { +                goto error; +            } + +            dot = PyUnicode_FindChar(package, '.', +                                        0, PyUnicode_GET_LENGTH(package), -1); +            if (dot == -2) { +                goto error; +            } + +            if (dot >= 0) { +                PyObject *substr = PyUnicode_Substring(package, 0, dot); +                if (substr == NULL) { +                    goto error; +                } +                Py_SETREF(package, substr); +            } +        } +    } + +    last_dot = PyUnicode_GET_LENGTH(package); +    if (last_dot == 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); +        goto error;      } -    if (given_fromlist == NULL) { -        fromlist = PyList_New(0); -        if (fromlist == NULL) { +    for (level_up = 1; level_up < level; level_up += 1) { +        last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); +        if (last_dot == -2) { +            goto error; +        } +        else if (last_dot == -1) { +            PyErr_SetString(PyExc_ValueError, +                            "attempted relative import beyond top-level " +                            "package");              goto error;          }      } -    else { -        fromlist = given_fromlist; -        Py_INCREF(fromlist); + +    base = PyUnicode_Substring(package, 0, last_dot); +    Py_DECREF(package); +    if (base == NULL || PyUnicode_GET_LENGTH(name) == 0) { +        return base;      } + +    abs_name = PyUnicode_FromFormat("%U.%U", base, name); +    Py_DECREF(base); +    return abs_name; + +  error: +    Py_XDECREF(package); +    return NULL; +} + +PyObject * +PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, +                                 PyObject *locals, PyObject *fromlist, +                                 int level) +{ +    _Py_IDENTIFIER(_find_and_load); +    _Py_IDENTIFIER(_handle_fromlist); +    PyObject *abs_name = NULL; +    PyObject *final_mod = NULL; +    PyObject *mod = NULL; +    PyObject *package = NULL; +    PyInterpreterState *interp = PyThreadState_GET()->interp; +    int has_from; +      if (name == NULL) {          PyErr_SetString(PyExc_ValueError, "Empty module name");          goto error; @@ -1415,140 +1516,44 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,          PyErr_SetString(PyExc_TypeError, "module name must be a string");          goto error;      } -    else if (PyUnicode_READY(name) < 0) { +    if (PyUnicode_READY(name) < 0) {          goto error;      }      if (level < 0) {          PyErr_SetString(PyExc_ValueError, "level must be >= 0");          goto error;      } -    else if (level > 0) { -        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; -            } -        } -        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"); -                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) { -                    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); -            } -        } - -        if (PyDict_GetItem(interp->modules, package) == NULL) { -            PyErr_Format(PyExc_SystemError, -                    "Parent module %R not loaded, cannot perform relative " -                    "import", package); +    if (level > 0) { +        abs_name = resolve_name(name, globals, level); +        if (abs_name == NULL)              goto error; -        }      }      else {  /* level == 0 */          if (PyUnicode_GET_LENGTH(name) == 0) {              PyErr_SetString(PyExc_ValueError, "Empty module name");              goto error;          } -        package = Py_None; -        Py_INCREF(package); -    } - -    if (level > 0) { -        Py_ssize_t last_dot = PyUnicode_GET_LENGTH(package); -        PyObject *base = NULL; -        int level_up = 1; - -        for (level_up = 1; level_up < level; level_up += 1) { -            last_dot = PyUnicode_FindChar(package, '.', 0, last_dot, -1); -            if (last_dot == -2) { -                goto error; -            } -            else if (last_dot == -1) { -                PyErr_SetString(PyExc_ValueError, -                                "attempted relative import beyond top-level " -                                "package"); -                goto error; -            } -        } - -        base = PyUnicode_Substring(package, 0, last_dot); -        if (base == NULL) -            goto error; - -        if (PyUnicode_GET_LENGTH(name) > 0) { -            PyObject *borrowed_dot, *seq = NULL; - -            borrowed_dot = _PyUnicode_FromId(&single_dot); -            seq = PyTuple_Pack(2, base, name); -            Py_DECREF(base); -            if (borrowed_dot == NULL || seq == NULL) { -                goto error; -            } - -            abs_name = PyUnicode_Join(borrowed_dot, seq); -            Py_DECREF(seq); -            if (abs_name == NULL) { -                goto error; -            } -        } -        else { -            abs_name = base; -        } -    } -    else {          abs_name = name;          Py_INCREF(abs_name);      } -#ifdef WITH_THREAD -    _PyImport_AcquireLock(); -#endif -   /* From this point forward, goto error_with_unlock! */ -    /* XXX interp->builtins_copy is NULL in subinterpreter! */ -    builtins_import = _PyDict_GetItemId(interp->builtins_copy ? -                                        interp->builtins_copy : -                                        interp->builtins, &PyId___import__); -    if (builtins_import == NULL) { -        PyErr_SetString(PyExc_ImportError, "__import__ not found"); -        goto error_with_unlock; -    } -    Py_INCREF(builtins_import); -      mod = PyDict_GetItem(interp->modules, abs_name);      if (mod == Py_None) {          PyObject *msg = PyUnicode_FromFormat("import of %R halted; "                                               "None in sys.modules", abs_name);          if (msg != NULL) { -            PyErr_SetImportError(msg, abs_name, NULL); +            PyErr_SetImportErrorSubclass(PyExc_ModuleNotFoundError, msg, +                    abs_name, NULL);              Py_DECREF(msg);          }          mod = NULL; -        goto error_with_unlock; +        goto error;      }      else if (mod != NULL) { +        _Py_IDENTIFIER(__spec__); +        _Py_IDENTIFIER(_initializing); +        _Py_IDENTIFIER(_lock_unlock_module);          PyObject *value = NULL;          PyObject *spec;          int initializing = 0; @@ -1571,91 +1576,83 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,              Py_DECREF(value);              if (initializing == -1)                  PyErr_Clear(); -        } -        if (initializing > 0) { -            /* _bootstrap._lock_unlock_module() releases the import lock */ -            value = _PyObject_CallMethodIdObjArgs(interp->importlib, -                                            &PyId__lock_unlock_module, abs_name, -                                            NULL); -            if (value == NULL) -                goto error; -            Py_DECREF(value); -        } -        else { +            if (initializing > 0) {  #ifdef WITH_THREAD -            if (_PyImport_ReleaseLock() < 0) { -                PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); -                goto error; -            } +                _PyImport_AcquireLock();  #endif +                /* _bootstrap._lock_unlock_module() releases the import lock */ +                value = _PyObject_CallMethodIdObjArgs(interp->importlib, +                                                &PyId__lock_unlock_module, abs_name, +                                                NULL); +                if (value == NULL) +                    goto error; +                Py_DECREF(value); +            }          }      }      else { +#ifdef WITH_THREAD +        _PyImport_AcquireLock(); +#endif          /* _bootstrap._find_and_load() releases the import lock */          mod = _PyObject_CallMethodIdObjArgs(interp->importlib,                                              &PyId__find_and_load, abs_name, -                                            builtins_import, NULL); +                                            interp->import_func, NULL);          if (mod == NULL) {              goto error;          }      } -    /* From now on we don't hold the import lock anymore. */ -    has_from = PyObject_IsTrue(fromlist); -    if (has_from < 0) -        goto error; +    has_from = 0; +    if (fromlist != NULL && fromlist != Py_None) { +        has_from = PyObject_IsTrue(fromlist); +        if (has_from < 0) +            goto error; +    }      if (!has_from) { -        if (level == 0 || PyUnicode_GET_LENGTH(name) > 0) { -            PyObject *front = NULL; -            PyObject *partition = NULL; -            PyObject *borrowed_dot = _PyUnicode_FromId(&single_dot); - -            if (borrowed_dot == NULL) { -                goto error; -            } +        Py_ssize_t len = PyUnicode_GET_LENGTH(name); +        if (level == 0 || len > 0) { +            Py_ssize_t dot; -            partition = PyUnicode_Partition(name, borrowed_dot); -            if (partition == NULL) { +            dot = PyUnicode_FindChar(name, '.', 0, len, 1); +            if (dot == -2) {                  goto error;              } -            if (PyUnicode_GET_LENGTH(PyTuple_GET_ITEM(partition, 1)) == 0) { +            if (dot == -1) {                  /* No dot in module name, simple exit */ -                Py_DECREF(partition);                  final_mod = mod;                  Py_INCREF(mod);                  goto error;              } -            front = PyTuple_GET_ITEM(partition, 0); -            Py_INCREF(front); -            Py_DECREF(partition); -              if (level == 0) { -                final_mod = PyObject_CallFunctionObjArgs(builtins_import, front, NULL); +                PyObject *front = PyUnicode_Substring(name, 0, dot); +                if (front == NULL) { +                    goto error; +                } + +                final_mod = PyImport_ImportModuleLevelObject(front, NULL, NULL, NULL, 0);                  Py_DECREF(front);              }              else { -                Py_ssize_t cut_off = PyUnicode_GET_LENGTH(name) - -                                        PyUnicode_GET_LENGTH(front); +                Py_ssize_t cut_off = len - dot;                  Py_ssize_t abs_name_len = PyUnicode_GET_LENGTH(abs_name);                  PyObject *to_return = PyUnicode_Substring(abs_name, 0,                                                          abs_name_len - cut_off); -                Py_DECREF(front);                  if (to_return == NULL) {                      goto error;                  }                  final_mod = PyDict_GetItem(interp->modules, to_return); +                Py_DECREF(to_return);                  if (final_mod == NULL) {                      PyErr_Format(PyExc_KeyError,                                   "%R not in sys.modules as expected",                                   to_return); +                    goto error;                  } -                else { -                    Py_INCREF(final_mod); -                } -                Py_DECREF(to_return); +                Py_INCREF(final_mod);              }          }          else { @@ -1666,24 +1663,14 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *given_globals,      else {          final_mod = _PyObject_CallMethodIdObjArgs(interp->importlib,                                                    &PyId__handle_fromlist, mod, -                                                  fromlist, builtins_import, +                                                  fromlist, interp->import_func,                                                    NULL);      } -    goto error; -  error_with_unlock: -#ifdef WITH_THREAD -    if (_PyImport_ReleaseLock() < 0) { -        PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); -    } -#endif    error:      Py_XDECREF(abs_name); -    Py_XDECREF(builtins_import);      Py_XDECREF(mod);      Py_XDECREF(package); -    Py_XDECREF(globals); -    Py_XDECREF(fromlist);      if (final_mod == NULL)          remove_importlib_frames();      return final_mod; @@ -1959,19 +1946,15 @@ exec_builtin_or_dynamic(PyObject *mod) {      def = PyModule_GetDef(mod);      if (def == NULL) { -        if (PyErr_Occurred()) { -            return -1; -        }          return 0;      } +      state = PyModule_GetState(mod); -    if (PyErr_Occurred()) { -        return -1; -    }      if (state) {          /* Already initialized; skip reload */          return 0;      } +      return PyModule_ExecDef(mod, def);  } | 
