Issue #13959: Re-implement imp.load_source() in imp.py.
This commit is contained in:
parent
4132368d0a
commit
16475adcbb
29
Lib/imp.py
29
Lib/imp.py
|
@ -14,7 +14,7 @@ from _imp import (lock_held, acquire_lock, release_lock, reload,
|
||||||
from _imp import (get_magic, get_tag, get_suffixes, cache_from_source,
|
from _imp import (get_magic, get_tag, get_suffixes, cache_from_source,
|
||||||
source_from_cache)
|
source_from_cache)
|
||||||
# Should be re-implemented here (and mostly deprecated)
|
# Should be re-implemented here (and mostly deprecated)
|
||||||
from _imp import (find_module, load_compiled, load_source, NullImporter,
|
from _imp import (find_module, load_compiled, NullImporter,
|
||||||
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
|
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
|
||||||
PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
|
PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
|
||||||
PY_CODERESOURCE, IMP_HOOK)
|
PY_CODERESOURCE, IMP_HOOK)
|
||||||
|
@ -25,6 +25,33 @@ from importlib import _bootstrap
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class _LoadSourceCompatibility(_bootstrap._SourceFileLoader):
|
||||||
|
|
||||||
|
"""Compatibility support for implementing load_source()."""
|
||||||
|
|
||||||
|
def __init__(self, fullname, path, file=None):
|
||||||
|
super().__init__(fullname, path)
|
||||||
|
self.file = file
|
||||||
|
|
||||||
|
def get_data(self, path):
|
||||||
|
"""Gross hack to contort SourceFileLoader to deal w/ load_source()'s bad
|
||||||
|
API."""
|
||||||
|
if path == self._path:
|
||||||
|
with self.file:
|
||||||
|
# Technically should be returning bytes, but
|
||||||
|
# SourceLoader.get_code() just passed what is returned to
|
||||||
|
# compile() which can handle str. And converting to bytes would
|
||||||
|
# require figuring out the encoding to decode to and
|
||||||
|
# tokenize.detect_encoding() only accepts bytes.
|
||||||
|
return self.file.read()
|
||||||
|
else:
|
||||||
|
return super().get_data(path)
|
||||||
|
|
||||||
|
|
||||||
|
def load_source(name, pathname, file=None):
|
||||||
|
return _LoadSourceCompatibility(name, pathname, file).load_module(name)
|
||||||
|
|
||||||
|
|
||||||
def load_package(name, path):
|
def load_package(name, path):
|
||||||
if os.path.isdir(path):
|
if os.path.isdir(path):
|
||||||
extensions = _bootstrap._suffix_list(PY_SOURCE)
|
extensions = _bootstrap._suffix_list(PY_SOURCE)
|
||||||
|
|
390
Python/import.c
390
Python/import.c
|
@ -904,26 +904,6 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Like strrchr(string, '/') but searches for the rightmost of either SEP
|
|
||||||
or ALTSEP, if the latter is defined.
|
|
||||||
*/
|
|
||||||
static Py_UCS4*
|
|
||||||
rightmost_sep(Py_UCS4 *s)
|
|
||||||
{
|
|
||||||
Py_UCS4 *found, c;
|
|
||||||
for (found = NULL; (c = *s); s++) {
|
|
||||||
if (c == SEP
|
|
||||||
#ifdef ALTSEP
|
|
||||||
|| c == ALTSEP
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
found = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like rightmost_sep, but operate on unicode objects. */
|
/* Like rightmost_sep, but operate on unicode objects. */
|
||||||
static Py_ssize_t
|
static Py_ssize_t
|
||||||
rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end)
|
rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end)
|
||||||
|
@ -1081,50 +1061,6 @@ make_source_pathname(PyObject *path)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a pathname for a Python source file, its time of last
|
|
||||||
modification, and a pathname for a compiled file, check whether the
|
|
||||||
compiled file represents the same version of the source. If so,
|
|
||||||
return a FILE pointer for the compiled file, positioned just after
|
|
||||||
the header; if not, return NULL.
|
|
||||||
Doesn't set an exception. */
|
|
||||||
|
|
||||||
static FILE *
|
|
||||||
check_compiled_module(PyObject *pathname, struct stat *srcstat, PyObject *cpathname)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
long magic;
|
|
||||||
long pyc_mtime;
|
|
||||||
long pyc_size;
|
|
||||||
|
|
||||||
fp = _Py_fopen(cpathname, "rb");
|
|
||||||
if (fp == NULL)
|
|
||||||
return NULL;
|
|
||||||
magic = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
if (magic != pyc_magic) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# %R has bad magic\n", cpathname);
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pyc_mtime = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
if (pyc_mtime != srcstat->st_mtime) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# %R has bad mtime\n", cpathname);
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pyc_size = PyMarshal_ReadLongFromFile(fp);
|
|
||||||
if (pyc_size != (srcstat->st_size & 0xFFFFFFFF)) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# %R has bad size\n", cpathname);
|
|
||||||
fclose(fp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# %R matches %R\n", cpathname, pathname);
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Read a code object from a file and check it for validity */
|
/* Read a code object from a file and check it for validity */
|
||||||
|
|
||||||
|
@ -1178,238 +1114,6 @@ load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a source file and return the corresponding code object */
|
|
||||||
|
|
||||||
static PyCodeObject *
|
|
||||||
parse_source_module(PyObject *pathname, FILE *fp)
|
|
||||||
{
|
|
||||||
PyCodeObject *co;
|
|
||||||
PyObject *pathbytes;
|
|
||||||
mod_ty mod;
|
|
||||||
PyCompilerFlags flags;
|
|
||||||
PyArena *arena;
|
|
||||||
|
|
||||||
pathbytes = PyUnicode_EncodeFSDefault(pathname);
|
|
||||||
if (pathbytes == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
arena = PyArena_New();
|
|
||||||
if (arena == NULL) {
|
|
||||||
Py_DECREF(pathbytes);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags.cf_flags = 0;
|
|
||||||
mod = PyParser_ASTFromFile(fp, PyBytes_AS_STRING(pathbytes), NULL,
|
|
||||||
Py_file_input, 0, 0, &flags,
|
|
||||||
NULL, arena);
|
|
||||||
if (mod != NULL)
|
|
||||||
co = PyAST_Compile(mod, PyBytes_AS_STRING(pathbytes), NULL, arena);
|
|
||||||
else
|
|
||||||
co = NULL;
|
|
||||||
Py_DECREF(pathbytes);
|
|
||||||
PyArena_Free(arena);
|
|
||||||
return co;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write a compiled module to a file, placing the time of last
|
|
||||||
modification of its source into the header.
|
|
||||||
Errors are ignored, if a write error occurs an attempt is made to
|
|
||||||
remove the file. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_compiled_module(PyCodeObject *co, PyObject *cpathname,
|
|
||||||
struct stat *srcstat)
|
|
||||||
{
|
|
||||||
Py_UCS4 *cpathname_ucs4;
|
|
||||||
FILE *fp;
|
|
||||||
time_t mtime = srcstat->st_mtime;
|
|
||||||
long size = srcstat->st_size & 0xFFFFFFFF;
|
|
||||||
PyObject *cpathname_tmp;
|
|
||||||
#ifdef MS_WINDOWS /* since Windows uses different permissions */
|
|
||||||
mode_t mode = srcstat->st_mode & ~S_IEXEC;
|
|
||||||
wchar_t *wdirname, *wpathname, *wpathname_tmp;
|
|
||||||
#else
|
|
||||||
mode_t dirmode = (srcstat->st_mode |
|
|
||||||
S_IXUSR | S_IXGRP | S_IXOTH |
|
|
||||||
S_IWUSR | S_IWGRP | S_IWOTH);
|
|
||||||
PyObject *dirbytes;
|
|
||||||
PyObject *cpathbytes, *cpathbytes_tmp;
|
|
||||||
#endif
|
|
||||||
int fd;
|
|
||||||
PyObject *dirname;
|
|
||||||
Py_UCS4 *dirsep;
|
|
||||||
int res, ok;
|
|
||||||
|
|
||||||
/* Ensure that the __pycache__ directory exists. */
|
|
||||||
cpathname_ucs4 = PyUnicode_AsUCS4Copy(cpathname);
|
|
||||||
if (!cpathname_ucs4)
|
|
||||||
return;
|
|
||||||
dirsep = rightmost_sep(cpathname_ucs4);
|
|
||||||
if (dirsep == NULL) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# no %s path found %R\n", CACHEDIR, cpathname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dirname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND,
|
|
||||||
cpathname_ucs4,
|
|
||||||
dirsep - cpathname_ucs4);
|
|
||||||
PyMem_Free(cpathname_ucs4);
|
|
||||||
if (dirname == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
wdirname = PyUnicode_AsUnicode(dirname);
|
|
||||||
if (wdirname == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res = CreateDirectoryW(wdirname, NULL);
|
|
||||||
ok = (res != 0);
|
|
||||||
if (!ok && GetLastError() == ERROR_ALREADY_EXISTS)
|
|
||||||
ok = 1;
|
|
||||||
#else
|
|
||||||
dirbytes = PyUnicode_EncodeFSDefault(dirname);
|
|
||||||
if (dirbytes == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res = mkdir(PyBytes_AS_STRING(dirbytes), dirmode);
|
|
||||||
Py_DECREF(dirbytes);
|
|
||||||
if (0 <= res)
|
|
||||||
ok = 1;
|
|
||||||
else
|
|
||||||
ok = (errno == EEXIST);
|
|
||||||
#endif
|
|
||||||
if (!ok) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# cannot create cache dir %R\n", dirname);
|
|
||||||
Py_DECREF(dirname);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Py_DECREF(dirname);
|
|
||||||
|
|
||||||
/* We first write to a tmp file and then take advantage
|
|
||||||
of atomic renaming (which *should* be true even under Windows).
|
|
||||||
As in importlib, we use id(something) to generate a pseudo-random
|
|
||||||
filename. mkstemp() can't be used since it doesn't allow specifying
|
|
||||||
the file access permissions.
|
|
||||||
*/
|
|
||||||
cpathname_tmp = PyUnicode_FromFormat("%U.%zd",
|
|
||||||
cpathname, (Py_ssize_t) co);
|
|
||||||
if (cpathname_tmp == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
wpathname = PyUnicode_AsUnicode(cpathname);
|
|
||||||
if (wpathname == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wpathname_tmp = PyUnicode_AsUnicode(cpathname_tmp);
|
|
||||||
if (wpathname_tmp == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)DeleteFileW(wpathname_tmp);
|
|
||||||
fd = _wopen(wpathname_tmp,
|
|
||||||
O_EXCL | O_CREAT | O_WRONLY | O_BINARY,
|
|
||||||
mode);
|
|
||||||
if (0 <= fd)
|
|
||||||
fp = fdopen(fd, "wb");
|
|
||||||
else
|
|
||||||
fp = NULL;
|
|
||||||
#else
|
|
||||||
cpathbytes_tmp = PyUnicode_EncodeFSDefault(cpathname_tmp);
|
|
||||||
Py_DECREF(cpathname_tmp);
|
|
||||||
if (cpathbytes_tmp == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cpathbytes = PyUnicode_EncodeFSDefault(cpathname);
|
|
||||||
if (cpathbytes == NULL) {
|
|
||||||
PyErr_Clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fd = open(PyBytes_AS_STRING(cpathbytes_tmp),
|
|
||||||
O_CREAT | O_EXCL | O_WRONLY, 0666);
|
|
||||||
if (0 <= fd)
|
|
||||||
fp = fdopen(fd, "wb");
|
|
||||||
else
|
|
||||||
fp = NULL;
|
|
||||||
#endif
|
|
||||||
if (fp == NULL) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr(
|
|
||||||
"# can't create %R\n", cpathname);
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
Py_DECREF(cpathname_tmp);
|
|
||||||
#else
|
|
||||||
Py_DECREF(cpathbytes);
|
|
||||||
Py_DECREF(cpathbytes_tmp);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
|
|
||||||
/* First write a 0 for mtime and size */
|
|
||||||
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
|
|
||||||
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
|
|
||||||
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
|
|
||||||
fflush(fp);
|
|
||||||
/* Now write the true mtime and size (as 32-bit fields) */
|
|
||||||
fseek(fp, 4L, 0);
|
|
||||||
assert(mtime <= 0xFFFFFFFF);
|
|
||||||
PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION);
|
|
||||||
PyMarshal_WriteLongToFile(size, fp, Py_MARSHAL_VERSION);
|
|
||||||
if (fflush(fp) != 0 || ferror(fp)) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# can't write %R\n", cpathname);
|
|
||||||
/* Don't keep partial file */
|
|
||||||
fclose(fp);
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
(void)DeleteFileW(wpathname_tmp);
|
|
||||||
Py_DECREF(cpathname_tmp);
|
|
||||||
#else
|
|
||||||
(void) unlink(PyBytes_AS_STRING(cpathbytes_tmp));
|
|
||||||
Py_DECREF(cpathbytes);
|
|
||||||
Py_DECREF(cpathbytes_tmp);
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
/* Do a (hopefully) atomic rename */
|
|
||||||
#ifdef MS_WINDOWS
|
|
||||||
if (!MoveFileExW(wpathname_tmp, wpathname, MOVEFILE_REPLACE_EXISTING)) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# can't write %R\n", cpathname);
|
|
||||||
/* Don't keep tmp file */
|
|
||||||
(void) DeleteFileW(wpathname_tmp);
|
|
||||||
Py_DECREF(cpathname_tmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Py_DECREF(cpathname_tmp);
|
|
||||||
#else
|
|
||||||
if (rename(PyBytes_AS_STRING(cpathbytes_tmp),
|
|
||||||
PyBytes_AS_STRING(cpathbytes))) {
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# can't write %R\n", cpathname);
|
|
||||||
/* Don't keep tmp file */
|
|
||||||
unlink(PyBytes_AS_STRING(cpathbytes_tmp));
|
|
||||||
Py_DECREF(cpathbytes);
|
|
||||||
Py_DECREF(cpathbytes_tmp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Py_DECREF(cpathbytes);
|
|
||||||
Py_DECREF(cpathbytes_tmp);
|
|
||||||
#endif
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("# wrote %R\n", cpathname);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
|
update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
|
||||||
{
|
{
|
||||||
|
@ -1474,76 +1178,6 @@ imp_fix_co_filename(PyObject *self, PyObject *args)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load a source module from a given file and return its module
|
|
||||||
object WITH INCREMENTED REFERENCE COUNT. If there's a matching
|
|
||||||
byte-compiled file, use that instead. */
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
load_source_module(PyObject *name, PyObject *pathname, FILE *fp)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
FILE *fpc;
|
|
||||||
PyObject *cpathname = NULL, *cpathbytes = NULL;
|
|
||||||
PyCodeObject *co;
|
|
||||||
PyObject *m = NULL;
|
|
||||||
|
|
||||||
if (fstat(fileno(fp), &st) != 0) {
|
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
|
||||||
"unable to get file status from %R",
|
|
||||||
pathname);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (sizeof st.st_mtime > 4) {
|
|
||||||
/* Python's .pyc timestamp handling presumes that the timestamp fits
|
|
||||||
in 4 bytes. Since the code only does an equality comparison,
|
|
||||||
ordering is not important and we can safely ignore the higher bits
|
|
||||||
(collisions are extremely unlikely).
|
|
||||||
*/
|
|
||||||
st.st_mtime &= 0xFFFFFFFF;
|
|
||||||
}
|
|
||||||
if (PyUnicode_READY(pathname) < 0)
|
|
||||||
return NULL;
|
|
||||||
cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag);
|
|
||||||
|
|
||||||
if (cpathname != NULL)
|
|
||||||
fpc = check_compiled_module(pathname, &st, cpathname);
|
|
||||||
else
|
|
||||||
fpc = NULL;
|
|
||||||
|
|
||||||
if (fpc) {
|
|
||||||
co = read_compiled_module(cpathname, fpc);
|
|
||||||
fclose(fpc);
|
|
||||||
if (co == NULL)
|
|
||||||
goto error;
|
|
||||||
update_compiled_module(co, pathname);
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("import %U # precompiled from %R\n",
|
|
||||||
name, cpathname);
|
|
||||||
m = PyImport_ExecCodeModuleObject(name, (PyObject *)co,
|
|
||||||
cpathname, cpathname);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
co = parse_source_module(pathname, fp);
|
|
||||||
if (co == NULL)
|
|
||||||
goto error;
|
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_FormatStderr("import %U # from %R\n",
|
|
||||||
name, pathname);
|
|
||||||
if (cpathname != NULL) {
|
|
||||||
PyObject *ro = PySys_GetObject("dont_write_bytecode");
|
|
||||||
if (ro == NULL || !PyObject_IsTrue(ro))
|
|
||||||
write_compiled_module(co, cpathname, &st);
|
|
||||||
}
|
|
||||||
m = PyImport_ExecCodeModuleObject(name, (PyObject *)co,
|
|
||||||
pathname, cpathname);
|
|
||||||
}
|
|
||||||
Py_DECREF(co);
|
|
||||||
|
|
||||||
error:
|
|
||||||
Py_XDECREF(cpathbytes);
|
|
||||||
Py_XDECREF(cpathname);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get source file -> unicode or None
|
/* Get source file -> unicode or None
|
||||||
* Returns the path to the py file if available, else the given path
|
* Returns the path to the py file if available, else the given path
|
||||||
|
@ -3426,29 +3060,6 @@ imp_load_dynamic(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
#endif /* HAVE_DYNAMIC_LOADING */
|
#endif /* HAVE_DYNAMIC_LOADING */
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
imp_load_source(PyObject *self, PyObject *args)
|
|
||||||
{
|
|
||||||
PyObject *name, *pathname;
|
|
||||||
PyObject *fob = NULL;
|
|
||||||
PyObject *m;
|
|
||||||
FILE *fp;
|
|
||||||
if (!PyArg_ParseTuple(args, "UO&|O:load_source",
|
|
||||||
&name,
|
|
||||||
PyUnicode_FSDecoder, &pathname,
|
|
||||||
&fob))
|
|
||||||
return NULL;
|
|
||||||
fp = get_file(pathname, fob, "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
Py_DECREF(pathname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
m = load_source_module(name, pathname, fp);
|
|
||||||
Py_DECREF(pathname);
|
|
||||||
fclose(fp);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
imp_reload(PyObject *self, PyObject *v)
|
imp_reload(PyObject *self, PyObject *v)
|
||||||
{
|
{
|
||||||
|
@ -3600,7 +3211,6 @@ static PyMethodDef imp_methods[] = {
|
||||||
#ifdef HAVE_DYNAMIC_LOADING
|
#ifdef HAVE_DYNAMIC_LOADING
|
||||||
{"load_dynamic", imp_load_dynamic, METH_VARARGS},
|
{"load_dynamic", imp_load_dynamic, METH_VARARGS},
|
||||||
#endif
|
#endif
|
||||||
{"load_source", imp_load_source, METH_VARARGS},
|
|
||||||
{"_fix_co_filename", imp_fix_co_filename, METH_VARARGS},
|
{"_fix_co_filename", imp_fix_co_filename, METH_VARARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue