mirror of
https://github.com/python/cpython.git
synced 2025-10-22 06:32:43 +00:00
Issue #3080: Use Unicode to import source and compiled modules
* Use Unicode for module name and path in the following functions: * get_file() * load_source_module(), parse_source_module() * make_compiled_pathname(), check_compiled_module(), read_compiled_module(), load_compiled_module(), write_compiled_module(), update_compiled_module() * On Windows, use CreateDirectoryW() instead of mkdir() * update_compiled_module() cannot fail anymore
This commit is contained in:
parent
c9abda0c04
commit
2f42ae53aa
1 changed files with 203 additions and 153 deletions
352
Python/import.c
352
Python/import.c
|
@ -107,8 +107,8 @@ typedef unsigned short mode_t;
|
||||||
/* MAGIC must change whenever the bytecode emitted by the compiler may no
|
/* MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||||
longer be understood by older implementations of the eval loop (usually
|
longer be understood by older implementations of the eval loop (usually
|
||||||
due to the addition of new opcodes)
|
due to the addition of new opcodes)
|
||||||
TAG must change for each major Python release. The magic number will take
|
TAG and PYC_TAG_UNICODE must change for each major Python release. The magic
|
||||||
care of any bytecode changes that occur during development.
|
number will take care of any bytecode changes that occur during development.
|
||||||
*/
|
*/
|
||||||
#define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
#define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24))
|
||||||
#define TAG "cpython-32"
|
#define TAG "cpython-32"
|
||||||
|
@ -118,6 +118,8 @@ static const Py_UNICODE CACHEDIR_UNICODE[] = {
|
||||||
/* Current magic word and string tag as globals. */
|
/* Current magic word and string tag as globals. */
|
||||||
static long pyc_magic = MAGIC;
|
static long pyc_magic = MAGIC;
|
||||||
static const char *pyc_tag = TAG;
|
static const char *pyc_tag = TAG;
|
||||||
|
static const Py_UNICODE PYC_TAG_UNICODE[] = {
|
||||||
|
'c', 'p', 'y', 't', 'h', 'o', 'n', '-', '3', '2', '\0'};
|
||||||
|
|
||||||
/* See _PyImport_FixupExtensionObject() below */
|
/* See _PyImport_FixupExtensionObject() below */
|
||||||
static PyObject *extensions = NULL;
|
static PyObject *extensions = NULL;
|
||||||
|
@ -745,8 +747,7 @@ remove_module(PyObject *name)
|
||||||
|
|
||||||
static PyObject * get_sourcefile(PyObject *filename);
|
static PyObject * get_sourcefile(PyObject *filename);
|
||||||
static PyObject *make_source_pathname(PyObject *pathname);
|
static PyObject *make_source_pathname(PyObject *pathname);
|
||||||
static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen,
|
static PyObject* make_compiled_pathname(Py_UNICODE *pathname, int debug);
|
||||||
int debug);
|
|
||||||
|
|
||||||
/* Execute a code object in a module and return the module object
|
/* Execute a code object in a module and return the module object
|
||||||
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
|
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
|
||||||
|
@ -867,32 +868,11 @@ 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 char *
|
|
||||||
rightmost_sep(char *s)
|
|
||||||
{
|
|
||||||
char *found, c;
|
|
||||||
for (found = NULL; (c = *s); s++) {
|
|
||||||
if (c == SEP
|
|
||||||
#ifdef ALTSEP
|
|
||||||
|| c == ALTSEP
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
found = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Like strrchr(string, '/') but searches for the rightmost of either SEP
|
/* Like strrchr(string, '/') but searches for the rightmost of either SEP
|
||||||
or ALTSEP, if the latter is defined.
|
or ALTSEP, if the latter is defined.
|
||||||
*/
|
*/
|
||||||
static Py_UNICODE*
|
static Py_UNICODE*
|
||||||
rightmost_sep_unicode(Py_UNICODE *s)
|
rightmost_sep(Py_UNICODE *s)
|
||||||
{
|
{
|
||||||
Py_UNICODE *found, c;
|
Py_UNICODE *found, c;
|
||||||
for (found = NULL; (c = *s); s++) {
|
for (found = NULL; (c = *s); s++) {
|
||||||
|
@ -912,15 +892,18 @@ rightmost_sep_unicode(Py_UNICODE *s)
|
||||||
/* Given a pathname for a Python source file, fill a buffer with the
|
/* Given a pathname for a Python source file, fill a buffer with the
|
||||||
pathname for the corresponding compiled file. Return the pathname
|
pathname for the corresponding compiled file. Return the pathname
|
||||||
for the compiled file, or NULL if there's no space in the buffer.
|
for the compiled file, or NULL if there's no space in the buffer.
|
||||||
Doesn't set an exception. */
|
Doesn't set an exception.
|
||||||
|
|
||||||
static char *
|
foo.py -> __pycache__/foo.<tag>.pyc */
|
||||||
make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug)
|
|
||||||
|
static PyObject*
|
||||||
|
make_compiled_pathname(Py_UNICODE *pathname, int debug)
|
||||||
{
|
{
|
||||||
/* foo.py -> __pycache__/foo.<tag>.pyc */
|
Py_UNICODE buf[MAXPATHLEN];
|
||||||
size_t len = strlen(pathname);
|
size_t buflen = (size_t)MAXPATHLEN;
|
||||||
|
size_t len = Py_UNICODE_strlen(pathname);
|
||||||
size_t i, save;
|
size_t i, save;
|
||||||
char *pos;
|
Py_UNICODE *pos;
|
||||||
int sep = SEP;
|
int sep = SEP;
|
||||||
|
|
||||||
/* Sanity check that the buffer has roughly enough space to hold what
|
/* Sanity check that the buffer has roughly enough space to hold what
|
||||||
|
@ -932,35 +915,37 @@ make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug)
|
||||||
sanity check before writing the extension to ensure we do not
|
sanity check before writing the extension to ensure we do not
|
||||||
overflow the buffer.
|
overflow the buffer.
|
||||||
*/
|
*/
|
||||||
if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen)
|
if (len + Py_UNICODE_strlen(CACHEDIR_UNICODE) + Py_UNICODE_strlen(PYC_TAG_UNICODE) + 5 > buflen)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Find the last path separator and copy everything from the start of
|
/* Find the last path separator and copy everything from the start of
|
||||||
the source string up to and including the separator.
|
the source string up to and including the separator.
|
||||||
*/
|
*/
|
||||||
if ((pos = rightmost_sep(pathname)) == NULL) {
|
pos = rightmost_sep(pathname);
|
||||||
|
if (pos == NULL) {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sep = *pos;
|
sep = *pos;
|
||||||
i = pos - pathname + 1;
|
i = pos - pathname + 1;
|
||||||
strncpy(buf, pathname, i);
|
Py_UNICODE_strncpy(buf, pathname, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
save = i;
|
save = i;
|
||||||
buf[i++] = '\0';
|
buf[i++] = '\0';
|
||||||
/* Add __pycache__/ */
|
/* Add __pycache__/ */
|
||||||
strcat(buf, CACHEDIR);
|
Py_UNICODE_strcat(buf, CACHEDIR_UNICODE);
|
||||||
i += strlen(CACHEDIR) - 1;
|
i += Py_UNICODE_strlen(CACHEDIR_UNICODE) - 1;
|
||||||
buf[i++] = sep;
|
buf[i++] = sep;
|
||||||
buf[i++] = '\0';
|
buf[i++] = '\0';
|
||||||
/* Add the base filename, but remove the .py or .pyw extension, since
|
/* Add the base filename, but remove the .py or .pyw extension, since
|
||||||
the tag name must go before the extension.
|
the tag name must go before the extension.
|
||||||
*/
|
*/
|
||||||
strcat(buf, pathname + save);
|
Py_UNICODE_strcat(buf, pathname + save);
|
||||||
if ((pos = strrchr(buf, '.')) != NULL)
|
pos = Py_UNICODE_strrchr(buf, '.');
|
||||||
|
if (pos != NULL)
|
||||||
*++pos = '\0';
|
*++pos = '\0';
|
||||||
strcat(buf, pyc_tag);
|
Py_UNICODE_strcat(buf, PYC_TAG_UNICODE);
|
||||||
/* The length test above assumes that we're only adding one character
|
/* The length test above assumes that we're only adding one character
|
||||||
to the end of what would normally be the extension. What if there
|
to the end of what would normally be the extension. What if there
|
||||||
is no extension, or the string ends in '.' or '.p', and otherwise
|
is no extension, or the string ends in '.' or '.p', and otherwise
|
||||||
|
@ -1010,11 +995,15 @@ make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug)
|
||||||
#if 0
|
#if 0
|
||||||
printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen);
|
printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen);
|
||||||
#endif
|
#endif
|
||||||
if (strlen(buf) + 5 > buflen)
|
len = Py_UNICODE_strlen(buf);
|
||||||
|
if (len + 5 > buflen)
|
||||||
return NULL;
|
return NULL;
|
||||||
strcat(buf, debug ? ".pyc" : ".pyo");
|
buf[len] = '.'; len++;
|
||||||
assert(strlen(buf) < buflen);
|
buf[len] = 'p'; len++;
|
||||||
return buf;
|
buf[len] = 'y'; len++;
|
||||||
|
buf[len] = debug ? 'c' : 'o'; len++;
|
||||||
|
assert(len <= buflen);
|
||||||
|
return PyUnicode_FromUnicode(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1042,12 +1031,12 @@ make_source_pathname(PyObject *pathobj)
|
||||||
must be the string __pycache__ or this is not a PEP 3147 style
|
must be the string __pycache__ or this is not a PEP 3147 style
|
||||||
path. It's possible for there to be only one slash.
|
path. It's possible for there to be only one slash.
|
||||||
*/
|
*/
|
||||||
right = rightmost_sep_unicode(pathname);
|
right = rightmost_sep(pathname);
|
||||||
if (right == NULL)
|
if (right == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
sep = *right;
|
sep = *right;
|
||||||
*right = '\0';
|
*right = '\0';
|
||||||
left = rightmost_sep_unicode(pathname);
|
left = rightmost_sep(pathname);
|
||||||
*right = sep;
|
*right = sep;
|
||||||
if (left == NULL)
|
if (left == NULL)
|
||||||
left = pathname;
|
left = pathname;
|
||||||
|
@ -1088,31 +1077,31 @@ make_source_pathname(PyObject *pathobj)
|
||||||
Doesn't set an exception. */
|
Doesn't set an exception. */
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
check_compiled_module(char *pathname, time_t mtime, char *cpathname)
|
check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
long magic;
|
long magic;
|
||||||
long pyc_mtime;
|
long pyc_mtime;
|
||||||
|
|
||||||
fp = fopen(cpathname, "rb");
|
fp = _Py_fopen(cpathname, "rb");
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
magic = PyMarshal_ReadLongFromFile(fp);
|
magic = PyMarshal_ReadLongFromFile(fp);
|
||||||
if (magic != pyc_magic) {
|
if (magic != pyc_magic) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# %s has bad magic\n", cpathname);
|
PySys_FormatStderr("# %R has bad magic\n", cpathname);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pyc_mtime = PyMarshal_ReadLongFromFile(fp);
|
pyc_mtime = PyMarshal_ReadLongFromFile(fp);
|
||||||
if (pyc_mtime != mtime) {
|
if (pyc_mtime != mtime) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# %s has bad mtime\n", cpathname);
|
PySys_FormatStderr("# %R has bad mtime\n", cpathname);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# %s matches %s\n", cpathname, pathname);
|
PySys_FormatStderr("# %R matches %R\n", cpathname, pathname);
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,7 +1109,7 @@ check_compiled_module(char *pathname, time_t mtime, char *cpathname)
|
||||||
/* Read a code object from a file and check it for validity */
|
/* Read a code object from a file and check it for validity */
|
||||||
|
|
||||||
static PyCodeObject *
|
static PyCodeObject *
|
||||||
read_compiled_module(char *cpathname, FILE *fp)
|
read_compiled_module(PyObject *cpathname, FILE *fp)
|
||||||
{
|
{
|
||||||
PyObject *co;
|
PyObject *co;
|
||||||
|
|
||||||
|
@ -1129,7 +1118,7 @@ read_compiled_module(char *cpathname, FILE *fp)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!PyCode_Check(co)) {
|
if (!PyCode_Check(co)) {
|
||||||
PyErr_Format(PyExc_ImportError,
|
PyErr_Format(PyExc_ImportError,
|
||||||
"Non-code object in %.200s", cpathname);
|
"Non-code object in %R", cpathname);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1141,7 +1130,7 @@ read_compiled_module(char *cpathname, FILE *fp)
|
||||||
module object WITH INCREMENTED REFERENCE COUNT */
|
module object WITH INCREMENTED REFERENCE COUNT */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
load_compiled_module(char *name, char *cpathname, FILE *fp)
|
load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp)
|
||||||
{
|
{
|
||||||
long magic;
|
long magic;
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
|
@ -1150,7 +1139,7 @@ load_compiled_module(char *name, char *cpathname, FILE *fp)
|
||||||
magic = PyMarshal_ReadLongFromFile(fp);
|
magic = PyMarshal_ReadLongFromFile(fp);
|
||||||
if (magic != pyc_magic) {
|
if (magic != pyc_magic) {
|
||||||
PyErr_Format(PyExc_ImportError,
|
PyErr_Format(PyExc_ImportError,
|
||||||
"Bad magic number in %.200s", cpathname);
|
"Bad magic number in %R", cpathname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
(void) PyMarshal_ReadLongFromFile(fp);
|
(void) PyMarshal_ReadLongFromFile(fp);
|
||||||
|
@ -1158,10 +1147,10 @@ load_compiled_module(char *name, char *cpathname, FILE *fp)
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("import %s # precompiled from %s\n",
|
PySys_FormatStderr("import %U # precompiled from %R\n",
|
||||||
name, cpathname);
|
name, cpathname);
|
||||||
m = PyImport_ExecCodeModuleWithPathnames(
|
m = PyImport_ExecCodeModuleObject(name, (PyObject *)co,
|
||||||
name, (PyObject *)co, cpathname, cpathname);
|
cpathname, cpathname);
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@ -1170,27 +1159,37 @@ load_compiled_module(char *name, char *cpathname, FILE *fp)
|
||||||
/* Parse a source file and return the corresponding code object */
|
/* Parse a source file and return the corresponding code object */
|
||||||
|
|
||||||
static PyCodeObject *
|
static PyCodeObject *
|
||||||
parse_source_module(const char *pathname, FILE *fp)
|
parse_source_module(PyObject *pathname, FILE *fp)
|
||||||
{
|
{
|
||||||
PyCodeObject *co = NULL;
|
PyCodeObject *co;
|
||||||
|
PyObject *pathbytes;
|
||||||
mod_ty mod;
|
mod_ty mod;
|
||||||
PyCompilerFlags flags;
|
PyCompilerFlags flags;
|
||||||
PyArena *arena = PyArena_New();
|
PyArena *arena;
|
||||||
if (arena == NULL)
|
|
||||||
|
pathbytes = PyUnicode_EncodeFSDefault(pathname);
|
||||||
|
if (pathbytes == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
arena = PyArena_New();
|
||||||
|
if (arena == NULL) {
|
||||||
|
Py_DECREF(pathbytes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
flags.cf_flags = 0;
|
flags.cf_flags = 0;
|
||||||
mod = PyParser_ASTFromFile(fp, pathname, NULL,
|
mod = PyParser_ASTFromFile(fp, PyBytes_AS_STRING(pathbytes), NULL,
|
||||||
Py_file_input, 0, 0, &flags,
|
Py_file_input, 0, 0, &flags,
|
||||||
NULL, arena);
|
NULL, arena);
|
||||||
if (mod) {
|
if (mod != NULL)
|
||||||
co = PyAST_Compile(mod, pathname, NULL, arena);
|
co = PyAST_Compile(mod, PyBytes_AS_STRING(pathbytes), NULL, arena);
|
||||||
}
|
else
|
||||||
|
co = NULL;
|
||||||
|
Py_DECREF(pathbytes);
|
||||||
PyArena_Free(arena);
|
PyArena_Free(arena);
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper to open a bytecode file for writing in exclusive mode */
|
/* Helper to open a bytecode file for writing in exclusive mode */
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
|
@ -1231,10 +1230,10 @@ open_exclusive(char *filename, mode_t mode)
|
||||||
remove the file. */
|
remove the file. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
|
write_compiled_module(PyCodeObject *co, PyObject *cpathname,
|
||||||
|
struct stat *srcstat)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *dirpath;
|
|
||||||
time_t mtime = srcstat->st_mtime;
|
time_t mtime = srcstat->st_mtime;
|
||||||
#ifdef MS_WINDOWS /* since Windows uses different permissions */
|
#ifdef MS_WINDOWS /* since Windows uses different permissions */
|
||||||
mode_t mode = srcstat->st_mode & ~S_IEXEC;
|
mode_t mode = srcstat->st_mode & ~S_IEXEC;
|
||||||
|
@ -1243,39 +1242,64 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
|
||||||
mode_t dirmode = (srcstat->st_mode |
|
mode_t dirmode = (srcstat->st_mode |
|
||||||
S_IXUSR | S_IXGRP | S_IXOTH |
|
S_IXUSR | S_IXGRP | S_IXOTH |
|
||||||
S_IWUSR | S_IWGRP | S_IWOTH);
|
S_IWUSR | S_IWGRP | S_IWOTH);
|
||||||
|
PyObject *dirbytes;
|
||||||
#endif
|
#endif
|
||||||
int saved;
|
PyObject *cpathbytes, *dirname;
|
||||||
|
Py_UNICODE *dirsep;
|
||||||
|
int res, ok;
|
||||||
|
|
||||||
/* Ensure that the __pycache__ directory exists. */
|
/* Ensure that the __pycache__ directory exists. */
|
||||||
dirpath = rightmost_sep(cpathname);
|
dirsep = rightmost_sep(PyUnicode_AS_UNICODE(cpathname));
|
||||||
if (dirpath == NULL) {
|
if (dirsep == NULL) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr(
|
PySys_FormatStderr("# no %s path found %R\n", CACHEDIR, cpathname);
|
||||||
"# no %s path found %s\n",
|
return;
|
||||||
CACHEDIR, cpathname);
|
}
|
||||||
|
dirname = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(cpathname),
|
||||||
|
dirsep - PyUnicode_AS_UNICODE(cpathname));
|
||||||
|
if (dirname == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saved = *dirpath;
|
|
||||||
*dirpath = '\0';
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
if (_mkdir(cpathname) < 0 && errno != EEXIST) {
|
res = CreateDirectoryW(PyUnicode_AS_UNICODE(dirname), NULL);
|
||||||
|
ok = (res != 0);
|
||||||
|
if (!ok && GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
ok = 1;
|
||||||
#else
|
#else
|
||||||
if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) {
|
dirbytes = PyUnicode_EncodeFSDefault(dirname);
|
||||||
#endif
|
if (dirbytes == NULL) {
|
||||||
*dirpath = saved;
|
PyErr_Clear();
|
||||||
if (Py_VerboseFlag)
|
|
||||||
PySys_WriteStderr(
|
|
||||||
"# cannot create cache dir %s\n", cpathname);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*dirpath = saved;
|
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);
|
||||||
|
|
||||||
fp = open_exclusive(cpathname, mode);
|
cpathbytes = PyUnicode_EncodeFSDefault(cpathname);
|
||||||
|
if (cpathbytes == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = open_exclusive(PyBytes_AS_STRING(cpathbytes), mode);
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr(
|
PySys_FormatStderr(
|
||||||
"# can't create %s\n", cpathname);
|
"# can't create %R\n", cpathname);
|
||||||
|
Py_DECREF(cpathbytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
|
PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION);
|
||||||
|
@ -1284,12 +1308,18 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
|
||||||
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
|
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
|
||||||
if (fflush(fp) != 0 || ferror(fp)) {
|
if (fflush(fp) != 0 || ferror(fp)) {
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# can't write %s\n", cpathname);
|
PySys_FormatStderr("# can't write %R\n", cpathname);
|
||||||
/* Don't keep partial file */
|
/* Don't keep partial file */
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
(void) unlink(cpathname);
|
#ifdef MS_WINDOWS
|
||||||
|
(void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname));
|
||||||
|
#else
|
||||||
|
(void) unlink(PyBytes_AS_STRING(cpathbytes));
|
||||||
|
#endif
|
||||||
|
Py_DECREF(cpathbytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Py_DECREF(cpathbytes);
|
||||||
/* Now write the true mtime */
|
/* Now write the true mtime */
|
||||||
fseek(fp, 4L, 0);
|
fseek(fp, 4L, 0);
|
||||||
assert(mtime < LONG_MAX);
|
assert(mtime < LONG_MAX);
|
||||||
|
@ -1297,7 +1327,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
|
||||||
fflush(fp);
|
fflush(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("# wrote %s\n", cpathname);
|
PySys_FormatStderr("# wrote %R\n", cpathname);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1324,26 +1354,18 @@ update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
update_compiled_module(PyCodeObject *co, char *pathname)
|
update_compiled_module(PyCodeObject *co, PyObject *newname)
|
||||||
{
|
{
|
||||||
PyObject *oldname, *newname;
|
PyObject *oldname;
|
||||||
|
|
||||||
newname = PyUnicode_DecodeFSDefault(pathname);
|
if (PyUnicode_Compare(co->co_filename, newname) == 0)
|
||||||
if (newname == NULL)
|
return;
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!PyUnicode_Compare(co->co_filename, newname)) {
|
|
||||||
Py_DECREF(newname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldname = co->co_filename;
|
oldname = co->co_filename;
|
||||||
Py_INCREF(oldname);
|
Py_INCREF(oldname);
|
||||||
update_code_filenames(co, oldname, newname);
|
update_code_filenames(co, oldname, newname);
|
||||||
Py_DECREF(oldname);
|
Py_DECREF(oldname);
|
||||||
Py_DECREF(newname);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load a source module from a given file and return its module
|
/* Load a source module from a given file and return its module
|
||||||
|
@ -1351,20 +1373,19 @@ update_compiled_module(PyCodeObject *co, char *pathname)
|
||||||
byte-compiled file, use that instead. */
|
byte-compiled file, use that instead. */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
load_source_module(char *name, char *pathname, FILE *fp)
|
load_source_module(PyObject *name, PyObject *pathname, FILE *fp)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
FILE *fpc;
|
FILE *fpc;
|
||||||
char buf[MAXPATHLEN+1];
|
PyObject *cpathname = NULL, *cpathbytes = NULL;
|
||||||
char *cpathname;
|
|
||||||
PyCodeObject *co;
|
PyCodeObject *co;
|
||||||
PyObject *m;
|
PyObject *m = NULL;
|
||||||
|
|
||||||
if (fstat(fileno(fp), &st) != 0) {
|
if (fstat(fileno(fp), &st) != 0) {
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
PyErr_Format(PyExc_RuntimeError,
|
||||||
"unable to get file status from '%s'",
|
"unable to get file status from %R",
|
||||||
pathname);
|
pathname);
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
#if SIZEOF_TIME_T > 4
|
#if SIZEOF_TIME_T > 4
|
||||||
/* Python's .pyc timestamp handling presumes that the timestamp fits
|
/* Python's .pyc timestamp handling presumes that the timestamp fits
|
||||||
|
@ -1374,41 +1395,50 @@ load_source_module(char *name, char *pathname, FILE *fp)
|
||||||
if (st.st_mtime >> 32) {
|
if (st.st_mtime >> 32) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"modification time overflows a 4 byte field");
|
"modification time overflows a 4 byte field");
|
||||||
return NULL;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cpathname = make_compiled_pathname(
|
cpathname = make_compiled_pathname(
|
||||||
pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag);
|
PyUnicode_AS_UNICODE(pathname),
|
||||||
if (cpathname != NULL &&
|
!Py_OptimizeFlag);
|
||||||
(fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) {
|
|
||||||
|
if (cpathname != NULL)
|
||||||
|
fpc = check_compiled_module(pathname, st.st_mtime, cpathname);
|
||||||
|
else
|
||||||
|
fpc = NULL;
|
||||||
|
|
||||||
|
if (fpc) {
|
||||||
co = read_compiled_module(cpathname, fpc);
|
co = read_compiled_module(cpathname, fpc);
|
||||||
fclose(fpc);
|
fclose(fpc);
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return NULL;
|
goto error;
|
||||||
if (update_compiled_module(co, pathname) < 0)
|
update_compiled_module(co, pathname);
|
||||||
return NULL;
|
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("import %s # precompiled from %s\n",
|
PySys_FormatStderr("import %U # precompiled from %R\n",
|
||||||
name, cpathname);
|
name, cpathname);
|
||||||
pathname = cpathname;
|
m = PyImport_ExecCodeModuleObject(name, (PyObject *)co,
|
||||||
|
cpathname, cpathname);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
co = parse_source_module(pathname, fp);
|
co = parse_source_module(pathname, fp);
|
||||||
if (co == NULL)
|
if (co == NULL)
|
||||||
return NULL;
|
goto error;
|
||||||
if (Py_VerboseFlag)
|
if (Py_VerboseFlag)
|
||||||
PySys_WriteStderr("import %s # from %s\n",
|
PySys_FormatStderr("import %U # from %R\n",
|
||||||
name, pathname);
|
name, pathname);
|
||||||
if (cpathname) {
|
if (cpathname != NULL) {
|
||||||
PyObject *ro = PySys_GetObject("dont_write_bytecode");
|
PyObject *ro = PySys_GetObject("dont_write_bytecode");
|
||||||
if (ro == NULL || !PyObject_IsTrue(ro))
|
if (ro == NULL || !PyObject_IsTrue(ro))
|
||||||
write_compiled_module(co, cpathname, &st);
|
write_compiled_module(co, cpathname, &st);
|
||||||
}
|
}
|
||||||
|
m = PyImport_ExecCodeModuleObject(name, (PyObject *)co,
|
||||||
|
pathname, cpathname);
|
||||||
}
|
}
|
||||||
m = PyImport_ExecCodeModuleWithPathnames(
|
|
||||||
name, (PyObject *)co, pathname, cpathname);
|
|
||||||
Py_DECREF(co);
|
Py_DECREF(co);
|
||||||
|
|
||||||
|
error:
|
||||||
|
Py_XDECREF(cpathbytes);
|
||||||
|
Py_XDECREF(cpathname);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2291,13 +2321,37 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case PY_SOURCE:
|
case PY_SOURCE: {
|
||||||
m = load_source_module(name, pathname, fp);
|
PyObject *nameobj, *pathobj;
|
||||||
|
nameobj = PyUnicode_FromString(name);
|
||||||
|
if (nameobj == NULL)
|
||||||
|
return NULL;
|
||||||
|
pathobj = PyUnicode_DecodeFSDefault(pathname);
|
||||||
|
if (pathobj == NULL) {
|
||||||
|
Py_DECREF(nameobj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m = load_source_module(nameobj, pathobj, fp);
|
||||||
|
Py_DECREF(nameobj);
|
||||||
|
Py_DECREF(pathobj);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case PY_COMPILED:
|
case PY_COMPILED: {
|
||||||
m = load_compiled_module(name, pathname, fp);
|
PyObject *nameobj, *pathobj;
|
||||||
|
nameobj = PyUnicode_FromString(name);
|
||||||
|
if (nameobj == NULL)
|
||||||
|
return NULL;
|
||||||
|
pathobj = PyUnicode_DecodeFSDefault(pathname);
|
||||||
|
if (pathobj == NULL) {
|
||||||
|
Py_DECREF(nameobj);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m = load_compiled_module(nameobj, pathobj, fp);
|
||||||
|
Py_DECREF(nameobj);
|
||||||
|
Py_DECREF(pathobj);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DYNAMIC_LOADING
|
#ifdef HAVE_DYNAMIC_LOADING
|
||||||
case C_EXTENSION: {
|
case C_EXTENSION: {
|
||||||
|
@ -3533,13 +3587,13 @@ imp_is_frozen(PyObject *self, PyObject *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
get_file(char *pathname, PyObject *fob, char *mode)
|
get_file(PyObject *pathname, PyObject *fob, char *mode)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
if (mode[0] == 'U')
|
if (mode[0] == 'U')
|
||||||
mode = "r" PY_STDIOTEXTMODE;
|
mode = "r" PY_STDIOTEXTMODE;
|
||||||
if (fob == NULL) {
|
if (fob == NULL) {
|
||||||
fp = fopen(pathname, mode);
|
fp = _Py_fopen(pathname, mode);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int fd = PyObject_AsFileDescriptor(fob);
|
int fd = PyObject_AsFileDescriptor(fob);
|
||||||
|
@ -3565,22 +3619,21 @@ error:
|
||||||
static PyObject *
|
static PyObject *
|
||||||
imp_load_compiled(PyObject *self, PyObject *args)
|
imp_load_compiled(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *name;
|
PyObject *name, *pathname;
|
||||||
PyObject *pathname;
|
|
||||||
PyObject *fob = NULL;
|
PyObject *fob = NULL;
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
if (!PyArg_ParseTuple(args, "sO&|O:load_compiled",
|
if (!PyArg_ParseTuple(args, "UO&|O:load_compiled",
|
||||||
&name,
|
&name,
|
||||||
PyUnicode_FSConverter, &pathname,
|
PyUnicode_FSDecoder, &pathname,
|
||||||
&fob))
|
&fob))
|
||||||
return NULL;
|
return NULL;
|
||||||
fp = get_file(PyBytes_AS_STRING(pathname), fob, "rb");
|
fp = get_file(pathname, fob, "rb");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
Py_DECREF(pathname);
|
Py_DECREF(pathname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
m = load_compiled_module(name, PyBytes_AS_STRING(pathname), fp);
|
m = load_compiled_module(name, pathname, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
Py_DECREF(pathname);
|
Py_DECREF(pathname);
|
||||||
return m;
|
return m;
|
||||||
|
@ -3615,22 +3668,21 @@ imp_load_dynamic(PyObject *self, PyObject *args)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
imp_load_source(PyObject *self, PyObject *args)
|
imp_load_source(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
char *name;
|
PyObject *name, *pathname;
|
||||||
PyObject *pathname;
|
|
||||||
PyObject *fob = NULL;
|
PyObject *fob = NULL;
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
if (!PyArg_ParseTuple(args, "sO&|O:load_source",
|
if (!PyArg_ParseTuple(args, "UO&|O:load_source",
|
||||||
&name,
|
&name,
|
||||||
PyUnicode_FSConverter, &pathname,
|
PyUnicode_FSDecoder, &pathname,
|
||||||
&fob))
|
&fob))
|
||||||
return NULL;
|
return NULL;
|
||||||
fp = get_file(PyBytes_AS_STRING(pathname), fob, "r");
|
fp = get_file(pathname, fob, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
Py_DECREF(pathname);
|
Py_DECREF(pathname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
m = load_source_module(name, PyBytes_AS_STRING(pathname), fp);
|
m = load_source_module(name, pathname, fp);
|
||||||
Py_DECREF(pathname);
|
Py_DECREF(pathname);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return m;
|
return m;
|
||||||
|
@ -3719,33 +3771,31 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws)
|
||||||
{
|
{
|
||||||
static char *kwlist[] = {"path", "debug_override", NULL};
|
static char *kwlist[] = {"path", "debug_override", NULL};
|
||||||
|
|
||||||
char buf[MAXPATHLEN+1];
|
PyObject *pathname, *cpathname;
|
||||||
PyObject *pathbytes;
|
|
||||||
char *cpathname;
|
|
||||||
PyObject *debug_override = NULL;
|
PyObject *debug_override = NULL;
|
||||||
int debug = !Py_OptimizeFlag;
|
int debug = !Py_OptimizeFlag;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(
|
if (!PyArg_ParseTupleAndKeywords(
|
||||||
args, kws, "O&|O", kwlist,
|
args, kws, "O&|O", kwlist,
|
||||||
PyUnicode_FSConverter, &pathbytes, &debug_override))
|
PyUnicode_FSDecoder, &pathname, &debug_override))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (debug_override != NULL &&
|
if (debug_override != NULL &&
|
||||||
(debug = PyObject_IsTrue(debug_override)) < 0) {
|
(debug = PyObject_IsTrue(debug_override)) < 0) {
|
||||||
Py_DECREF(pathbytes);
|
Py_DECREF(pathname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpathname = make_compiled_pathname(
|
cpathname = make_compiled_pathname(
|
||||||
PyBytes_AS_STRING(pathbytes),
|
PyUnicode_AS_UNICODE(pathname),
|
||||||
buf, MAXPATHLEN+1, debug);
|
debug);
|
||||||
Py_DECREF(pathbytes);
|
Py_DECREF(pathname);
|
||||||
|
|
||||||
if (cpathname == NULL) {
|
if (cpathname == NULL) {
|
||||||
PyErr_Format(PyExc_SystemError, "path buffer too short");
|
PyErr_Format(PyExc_SystemError, "path buffer too short");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return PyUnicode_DecodeFSDefault(buf);
|
return cpathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(doc_cache_from_source,
|
PyDoc_STRVAR(doc_cache_from_source,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue