diff options
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 816 |
1 files changed, 602 insertions, 214 deletions
diff --git a/Python/import.c b/Python/import.c index 5d80983..23752ee 100644 --- a/Python/import.c +++ b/Python/import.c @@ -5,13 +5,9 @@ #include "Python-ast.h" #undef Yield /* undefine macro conflicting with winbase.h */ -#include "pyarena.h" -#include "pythonrun.h" #include "errcode.h" #include "marshal.h" #include "code.h" -#include "compile.h" -#include "eval.h" #include "osdefs.h" #include "importdl.h" @@ -25,6 +21,8 @@ extern "C" { #ifdef MS_WINDOWS /* for stat.st_mode */ typedef unsigned short mode_t; +/* for _mkdir */ +#include <direct.h> #endif @@ -43,6 +41,15 @@ typedef unsigned short mode_t; The current working scheme is to increment the previous value by 10. + Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic + number also includes a new "magic tag", i.e. a human readable string used + to represent the magic number in __pycache__ directories. When you change + the magic number, you must also set a new unique magic tag. Generally this + can be named after the Python major version of the magic number bump, but + it can really be anything, as long as it's different than anything else + that's come before. The tags are included in the following table, starting + with Python 3.2a0. + Known values: Python 1.5: 20121 Python 1.5.1: 20121 @@ -78,26 +85,39 @@ typedef unsigned short mode_t; 3040 (added signature annotations) 3050 (print becomes a function) 3060 (PEP 3115 metaclass syntax) - 3070 (PEP 3109 raise changes) - 3080 (PEP 3137 make __file__ and __name__ unicode) - 3090 (kill str8 interning) - 3100 (merge from 2.6a0, see 62151) - 3102 (__file__ points to source file) - Python 3.0a4: 3110 (WITH_CLEANUP optimization). - Python 3.0a5: 3130 (lexical exception stacking, including POP_EXCEPT) - Python 3.1a0: 3140 (optimize list, set and dict comprehensions: + 3061 (string literals become unicode) + 3071 (PEP 3109 raise changes) + 3081 (PEP 3137 make __file__ and __name__ unicode) + 3091 (kill str8 interning) + 3101 (merge from 2.6a0, see 62151) + 3103 (__file__ points to source file) + Python 3.0a4: 3111 (WITH_CLEANUP optimization). + Python 3.0a5: 3131 (lexical exception stacking, including POP_EXCEPT) + Python 3.1a0: 3141 (optimize list, set and dict comprehensions: change LIST_APPEND and SET_ADD, add MAP_ADD) - Python 3.1a0: 3150 (optimize conditional branches: + Python 3.1a0: 3151 (optimize conditional branches: introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) + Python 3.2a0: 3160 (add SETUP_WITH) + tag: cpython-32 + Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) + tag: cpython-32 + Python 3.2a2 3180 (add DELETE_DEREF) */ -#define MAGIC (3150 | ((long)'\r'<<16) | ((long)'\n'<<24)) -/* Magic word as global; note that _PyImport_Init() can change the - value of this global to accommodate for alterations of how the - compiler works which are enabled by command line switches. */ +/* MAGIC must change whenever the bytecode emitted by the compiler may no + longer be understood by older implementations of the eval loop (usually + due to the addition of new opcodes) + TAG must change for each major Python release. The magic number will take + care of any bytecode changes that occur during development. +*/ +#define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define TAG "cpython-32" +#define CACHEDIR "__pycache__" +/* Current magic word and string tag as globals. */ static long pyc_magic = MAGIC; +static const char *pyc_tag = TAG; -/* See _PyImport_FixupExtension() below */ +/* See _PyImport_FixupExtensionUnicode() below */ static PyObject *extensions = NULL; /* This table is defined in config.c: */ @@ -160,13 +180,6 @@ _PyImport_Init(void) filetab->suffix = ".pyo"; } } - - { - /* Fix the pyc_magic so that byte compiled code created - using the all-Unicode method doesn't interfere with - code created in normal operation mode. */ - pyc_magic = MAGIC + 1; - } } void @@ -302,14 +315,27 @@ _PyImport_ReleaseLock(void) return 1; } -/* This function used to be called from PyOS_AfterFork to ensure that newly - created child processes do not share locks with the parent, but for some - reason only on AIX systems. Instead of re-initializing the lock, we now - acquire the import lock around fork() calls. */ +/* This function is called from PyOS_AfterFork to ensure that newly + created child processes do not share locks with the parent. + We now acquire the import lock around fork() calls but on some platforms + (Solaris 9 and earlier? see isue7242) that still left us with problems. */ void _PyImport_ReInitLock(void) { + if (import_lock != NULL) + import_lock = PyThread_allocate_lock(); + if (import_lock_level > 1) { + /* Forked as a side effect of import */ + long me = PyThread_get_thread_ident(); + PyThread_acquire_lock(import_lock, 0); + /* XXX: can the previous line fail? */ + import_lock_thread = me; + import_lock_level--; + } else { + import_lock_thread = -1; + import_lock_level = 0; + } } #endif @@ -520,7 +546,7 @@ PyImport_Cleanup(void) } -/* Helper for pythonrun.c -- return magic number */ +/* Helper for pythonrun.c -- return magic number and tag. */ long PyImport_GetMagicNumber(void) @@ -529,24 +555,30 @@ PyImport_GetMagicNumber(void) } +const char * +PyImport_GetMagicTag(void) +{ + return pyc_tag; +} + /* Magic for extension modules (built-in as well as dynamically loaded). To prevent initializing an extension module more than once, we keep a static dictionary 'extensions' keyed by module name (for built-in modules) or by filename (for dynamically loaded modules), containing these modules. A copy of the module's - dictionary is stored by calling _PyImport_FixupExtension() + dictionary is stored by calling _PyImport_FixupExtensionUnicode() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling - _PyImport_FindExtension(). + _PyImport_FindExtensionUnicode(). - Modules which do support multiple multiple initialization set - their m_size field to a non-negative number (indicating the size - of the module-specific state). They are still recorded in the - extensions dictionary, to avoid loading shared libraries twice. + Modules which do support multiple initialization set their m_size + field to a non-negative number (indicating the size of the + module-specific state). They are still recorded in the extensions + dictionary, to avoid loading shared libraries twice. */ int -_PyImport_FixupExtension(PyObject *mod, char *name, char *filename) +_PyImport_FixupExtensionUnicode(PyObject *mod, char *name, PyObject *filename) { PyObject *modules, *dict; struct PyModuleDef *def; @@ -586,18 +618,31 @@ _PyImport_FixupExtension(PyObject *mod, char *name, char *filename) if (def->m_base.m_copy == NULL) return -1; } - PyDict_SetItemString(extensions, filename, (PyObject*)def); + PyDict_SetItem(extensions, filename, (PyObject*)def); return 0; } +int +_PyImport_FixupBuiltin(PyObject *mod, char *name) +{ + int res; + PyObject *filename; + filename = PyUnicode_FromString(name); + if (filename == NULL) + return -1; + res = _PyImport_FixupExtensionUnicode(mod, name, filename); + Py_DECREF(filename); + return res; +} + PyObject * -_PyImport_FindExtension(char *name, char *filename) +_PyImport_FindExtensionUnicode(char *name, PyObject *filename) { PyObject *mod, *mdict; PyModuleDef* def; if (extensions == NULL) return NULL; - def = (PyModuleDef*)PyDict_GetItemString(extensions, filename); + def = (PyModuleDef*)PyDict_GetItem(extensions, filename); if (def == NULL) return NULL; if (def->m_size == -1) { @@ -628,12 +673,23 @@ _PyImport_FindExtension(char *name, char *filename) return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # previously loaded (%s)\n", + PySys_FormatStderr("import %s # previously loaded (%U)\n", name, filename); return mod; } +PyObject * +_PyImport_FindBuiltin(char *name) +{ + PyObject *res, *filename; + filename = PyUnicode_FromString(name); + if (filename == NULL) + return NULL; + res = _PyImport_FindExtensionUnicode(name, filename); + Py_DECREF(filename); + return res; +} /* Get the module object corresponding to a module name. First check the modules dictionary if there's one there, @@ -664,7 +720,7 @@ PyImport_AddModule(const char *name) /* Remove name from sys.modules, if it's there. */ static void -_RemoveModule(const char *name) +remove_module(const char *name) { PyObject *modules = PyImport_GetModuleDict(); if (PyDict_GetItemString(modules, name) == NULL) @@ -674,7 +730,10 @@ _RemoveModule(const char *name) "sys.modules failed"); } -static PyObject * get_sourcefile(const char *file); +static PyObject * get_sourcefile(char *file); +static char *make_source_pathname(char *pathname, char *buf); +static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, + int debug); /* Execute a code object in a module and return the module object * WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is @@ -682,16 +741,28 @@ static PyObject * get_sourcefile(const char *file); * in sys.modules. The caller may wish to restore the original * module object (if any) in this case; PyImport_ReloadModule is an * example. + * + * Note that PyImport_ExecCodeModuleWithPathnames() is the preferred, richer + * interface. The other two exist primarily for backward compatibility. */ PyObject * PyImport_ExecCodeModule(char *name, PyObject *co) { - return PyImport_ExecCodeModuleEx(name, co, (char *)NULL); + return PyImport_ExecCodeModuleWithPathnames( + name, co, (char *)NULL, (char *)NULL); } PyObject * PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) { + return PyImport_ExecCodeModuleWithPathnames( + name, co, pathname, (char *)NULL); +} + +PyObject * +PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, + char *cpathname) +{ PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; @@ -721,7 +792,21 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) PyErr_Clear(); /* Not important enough to report */ Py_DECREF(v); - v = PyEval_EvalCode((PyCodeObject *)co, d, d); + /* Remember the pyc path name as the __cached__ attribute. */ + if (cpathname == NULL) { + v = Py_None; + Py_INCREF(v); + } + else if ((v = PyUnicode_FromString(cpathname)) == NULL) { + PyErr_Clear(); /* Not important enough to report */ + v = Py_None; + Py_INCREF(v); + } + if (PyDict_SetItemString(d, "__cached__", v) != 0) + PyErr_Clear(); /* Not important enough to report */ + Py_DECREF(v); + + v = PyEval_EvalCode(co, d, d); if (v == NULL) goto error; Py_DECREF(v); @@ -738,37 +823,194 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) return m; error: - _RemoveModule(name); + remove_module(name); return NULL; } +/* 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; +} + + /* Given a pathname for a Python source file, fill a buffer with the pathname for the corresponding compiled file. Return the pathname for the compiled file, or NULL if there's no space in the buffer. Doesn't set an exception. */ static char * -make_compiled_pathname(char *pathname, char *buf, size_t buflen) +make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) { + /* foo.py -> __pycache__/foo.<tag>.pyc */ size_t len = strlen(pathname); - if (len+2 > buflen) + size_t i, save; + char *pos; + int sep = SEP; + + /* Sanity check that the buffer has roughly enough space to hold what + will eventually be the full path to the compiled file. The 5 extra + bytes include the slash afer __pycache__, the two extra dots, the + extra trailing character ('c' or 'o') and null. This isn't exact + because the contents of the buffer can affect how many actual + characters of the string get into the buffer. We'll do a final + sanity check before writing the extension to ensure we do not + overflow the buffer. + */ + if (len + strlen(CACHEDIR) + strlen(pyc_tag) + 5 > buflen) return NULL; -#ifdef MS_WINDOWS - /* Treat .pyw as if it were .py. The case of ".pyw" must match - that used in _PyImport_StandardFiletab. */ - if (len >= 4 && strcmp(&pathname[len-4], ".pyw") == 0) - --len; /* pretend 'w' isn't there */ + /* Find the last path separator and copy everything from the start of + the source string up to and including the separator. + */ + if ((pos = rightmost_sep(pathname)) == NULL) { + i = 0; + } + else { + sep = *pos; + i = pos - pathname + 1; + strncpy(buf, pathname, i); + } + + save = i; + buf[i++] = '\0'; + /* Add __pycache__/ */ + strcat(buf, CACHEDIR); + i += strlen(CACHEDIR) - 1; + buf[i++] = sep; + buf[i++] = '\0'; + /* Add the base filename, but remove the .py or .pyw extension, since + the tag name must go before the extension. + */ + strcat(buf, pathname + save); + if ((pos = strrchr(buf, '.')) != NULL) + *++pos = '\0'; + strcat(buf, pyc_tag); + /* 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 + is no extension, or the string ends in '.' or '.p', and otherwise + fills the buffer? By appending 4 more characters onto the string + here, we could overrun the buffer. + + As a simple example, let's say buflen=32 and the input string is + 'xxx.py'. strlen() would be 6 and the test above would yield: + + (6 + 11 + 10 + 5 == 32) > 32 + + which is false and so the name mangling would continue. This would + be fine because we'd end up with this string in buf: + + __pycache__/xxx.cpython-32.pyc\0 + + strlen(of that) == 30 + the nul fits inside a 32 character buffer. + We can even handle an input string of say 'xxxxx' above because + that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name + mangling that yields: + + __pycache__/xxxxxcpython-32.pyc\0 + + which is 32 characters including the nul, and thus fits in the + buffer. However, an input string of 'xxxxxx' would yield a result + string of: + + __pycache__/xxxxxxcpython-32.pyc\0 + + which is 33 characters long (including the nul), thus overflowing + the buffer, even though the first test would fail, i.e.: the input + string is also 6 characters long, so 32 > 32 is false. + + The reason the first test fails but we still overflow the buffer is + that the test above only expects to add one extra character to be + added to the extension, and here we're adding three (pyc). We + don't add the first dot, so that reclaims one of expected + positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed + dot - 1 expected extra == 1 overflowed). + + The best we can do is ensure that we still have enough room in the + target buffer before we write the extension. Because it's always + only the extension that can cause the overflow, and never the other + path bytes we've written, it's sufficient to just do one more test + here. Still, the assertion that follows can't hurt. + */ +#if 0 + printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); #endif - memcpy(buf, pathname, len); - buf[len] = Py_OptimizeFlag ? 'o' : 'c'; - buf[len+1] = '\0'; - + if (strlen(buf) + 5 > buflen) + return NULL; + strcat(buf, debug ? ".pyc" : ".pyo"); + assert(strlen(buf) < buflen); return buf; } +/* Given a pathname to a Python byte compiled file, return the path to the + source file, if the path matches the PEP 3147 format. This does not check + for any file existence, however, if the pyc file name does not match PEP + 3147 style, NULL is returned. buf must be at least as big as pathname; + the resulting path will always be shorter. */ + +static char * +make_source_pathname(char *pathname, char *buf) +{ + /* __pycache__/foo.<tag>.pyc -> foo.py */ + size_t i, j; + char *left, *right, *dot0, *dot1, sep; + + /* Look back two slashes from the end. In between these two slashes + must be the string __pycache__ or this is not a PEP 3147 style + path. It's possible for there to be only one slash. + */ + if ((right = rightmost_sep(pathname)) == NULL) + return NULL; + sep = *right; + *right = '\0'; + left = rightmost_sep(pathname); + *right = sep; + if (left == NULL) + left = pathname; + else + left++; + if (right-left != strlen(CACHEDIR) || + strncmp(left, CACHEDIR, right-left) != 0) + return NULL; + + /* Now verify that the path component to the right of the last slash + has two dots in it. + */ + if ((dot0 = strchr(right + 1, '.')) == NULL) + return NULL; + if ((dot1 = strchr(dot0 + 1, '.')) == NULL) + return NULL; + /* Too many dots? */ + if (strchr(dot1 + 1, '.') != NULL) + return NULL; + + /* This is a PEP 3147 path. Start by copying everything from the + start of pathname up to and including the leftmost slash. Then + copy the file's basename, removing the magic tag and adding a .py + suffix. + */ + strncpy(buf, pathname, (i=left-pathname)); + strncpy(buf+i, right+1, (j=dot0-right)); + strcpy(buf+i+j, "py"); + return buf; +} + /* 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, @@ -849,7 +1091,8 @@ load_compiled_module(char *name, char *cpathname, FILE *fp) if (Py_VerboseFlag) PySys_WriteStderr("import %s # precompiled from %s\n", name, cpathname); - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, cpathname); + m = PyImport_ExecCodeModuleWithPathnames( + name, (PyObject *)co, cpathname, cpathname); Py_DECREF(co); return m; @@ -922,12 +1165,42 @@ static void write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) { FILE *fp; + char *dirpath; time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; #else mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; + mode_t dirmode = (srcstat->st_mode | + S_IXUSR | S_IXGRP | S_IXOTH | + S_IWUSR | S_IWGRP | S_IWOTH); +#endif + int saved; + + /* Ensure that the __pycache__ directory exists. */ + dirpath = rightmost_sep(cpathname); + if (dirpath == NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "# no %s path found %s\n", + CACHEDIR, cpathname); + return; + } + saved = *dirpath; + *dirpath = '\0'; + +#ifdef MS_WINDOWS + if (_mkdir(cpathname) < 0 && errno != EEXIST) { +#else + if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { #endif + *dirpath = saved; + if (Py_VerboseFlag) + PySys_WriteStderr( + "# cannot create cache dir %s\n", cpathname); + return; + } + *dirpath = saved; fp = open_exclusive(cpathname, mode); if (fp == NULL) { @@ -1035,8 +1308,8 @@ load_source_module(char *name, char *pathname, FILE *fp) return NULL; } #endif - cpathname = make_compiled_pathname(pathname, buf, - (size_t)MAXPATHLEN + 1); + cpathname = make_compiled_pathname( + pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); if (cpathname != NULL && (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { co = read_compiled_module(cpathname, fpc); @@ -1063,7 +1336,8 @@ load_source_module(char *name, char *pathname, FILE *fp) write_compiled_module(co, cpathname, &st); } } - m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname); + m = PyImport_ExecCodeModuleWithPathnames( + name, (PyObject *)co, pathname, cpathname); Py_DECREF(co); return m; @@ -1073,7 +1347,7 @@ load_source_module(char *name, char *pathname, FILE *fp) * Returns the path to the py file if available, else the given path */ static PyObject * -get_sourcefile(const char *file) +get_sourcefile(char *file) { char py[MAXPATHLEN + 1]; Py_ssize_t len; @@ -1090,8 +1364,15 @@ get_sourcefile(const char *file) return PyUnicode_DecodeFSDefault(file); } - strncpy(py, file, len-1); - py[len-1] = '\0'; + /* Start by trying to turn PEP 3147 path into source path. If that + * fails, just chop off the trailing character, i.e. legacy pyc path + * to py. + */ + if (make_source_pathname(file, py) == NULL) { + strncpy(py, file, len-1); + py[len-1] = '\0'; + } + if (stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { u = PyUnicode_DecodeFSDefault(py); @@ -1390,8 +1671,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, if (!v) return NULL; if (PyUnicode_Check(v)) { - v = PyUnicode_AsEncodedString(v, - Py_FileSystemDefaultEncoding, NULL); + v = PyUnicode_EncodeFSDefault(v); if (v == NULL) return NULL; } @@ -1461,14 +1741,16 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, return &fd_package; } else { - char warnstr[MAXPATHLEN+80]; - sprintf(warnstr, "Not importing directory " - "'%.*s': missing __init__.py", - MAXPATHLEN, buf); - if (PyErr_WarnEx(PyExc_ImportWarning, - warnstr, 1)) { + int err; + PyObject *unicode = PyUnicode_DecodeFSDefault(buf); + if (unicode == NULL) + return NULL; + err = PyErr_WarnFormat(PyExc_ImportWarning, 1, + "Not importing directory '%U': missing __init__.py", + unicode); + Py_DECREF(unicode); + if (err) return NULL; - } } } #endif @@ -1548,22 +1830,6 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, return fdp; } -/* Helpers for main.c - * Find the source file corresponding to a named module - */ -struct filedescr * -_PyImport_FindModule(const char *name, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) -{ - return find_module((char *) name, (char *) name, path, - buf, buflen, p_fp, p_loader); -} - -PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr * fd) -{ - return fd->type == PY_SOURCE || fd->type == PY_COMPILED; -} - /* case_ok(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) * The arguments here are tricky, best shown by example: * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 @@ -1718,8 +1984,8 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) #endif } - #ifdef HAVE_STAT + /* Helper to look for __init__.py or __init__.py[co] in potential package */ static int find_init_module(char *buf) @@ -1771,15 +2037,52 @@ find_init_module(char *buf) static int init_builtin(char *); /* Forward */ +static PyObject* +load_builtin(char *name, char *pathname, int type) +{ + PyObject *m, *modules; + int err; + + if (pathname != NULL && pathname[0] != '\0') + name = pathname; + + if (type == C_BUILTIN) + err = init_builtin(name); + else + err = PyImport_ImportFrozenModule(name); + if (err < 0) + return NULL; + if (err == 0) { + PyErr_Format(PyExc_ImportError, + "Purported %s module %.200s not found", + type == C_BUILTIN ? + "builtin" : "frozen", + name); + return NULL; + } + + modules = PyImport_GetModuleDict(); + m = PyDict_GetItemString(modules, name); + if (m == NULL) { + PyErr_Format( + PyExc_ImportError, + "%s module %.200s not properly initialized", + type == C_BUILTIN ? + "builtin" : "frozen", + name); + return NULL; + } + Py_INCREF(m); + return m; +} + /* Load an external module using the default search path and return its module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) { - PyObject *modules; PyObject *m; - int err; /* First check that there's an open file (if we need one) */ switch (type) { @@ -1815,34 +2118,7 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) case C_BUILTIN: case PY_FROZEN: - if (pathname != NULL && pathname[0] != '\0') - name = pathname; - if (type == C_BUILTIN) - err = init_builtin(name); - else - err = PyImport_ImportFrozenModule(name); - if (err < 0) - return NULL; - if (err == 0) { - PyErr_Format(PyExc_ImportError, - "Purported %s module %.200s not found", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - modules = PyImport_GetModuleDict(); - m = PyDict_GetItemString(modules, name); - if (m == NULL) { - PyErr_Format( - PyExc_ImportError, - "%s module %.200s not properly initialized", - type == C_BUILTIN ? - "builtin" : "frozen", - name); - return NULL; - } - Py_INCREF(m); + m = load_builtin(name, pathname, type); break; case IMP_HOOK: { @@ -1876,7 +2152,7 @@ init_builtin(char *name) { struct _inittab *p; - if (_PyImport_FindExtension(name, name) != NULL) + if (_PyImport_FindBuiltin(name) != NULL) return 1; for (p = PyImport_Inittab; p->name != NULL; p++) { @@ -1893,7 +2169,7 @@ init_builtin(char *name) mod = (*p->initfunc)(); if (mod == 0) return -1; - if (_PyImport_FixupExtension(mod, name, name) < 0) + if (_PyImport_FixupBuiltin(mod, name) < 0) return -1; /* FixupExtension has put the module into sys.modules, so we can release our own reference. */ @@ -2510,14 +2786,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, char *subname; PyObject *submod; char *p; - if (!Py_FileSystemDefaultEncoding) { - item8 = PyUnicode_EncodeASCII(PyUnicode_AsUnicode(item), - PyUnicode_GetSize(item), - NULL); - } else { - item8 = PyUnicode_AsEncodedString(item, - Py_FileSystemDefaultEncoding, NULL); - } + item8 = PyUnicode_EncodeFSDefault(item); if (!item8) { PyErr_SetString(PyExc_ValueError, "Cannot encode path item"); return 0; @@ -2739,7 +3008,7 @@ PyImport_ReloadModule(PyObject *m) more accurately -- it invokes the __import__() function from the builtins of the current globals. This means that the import is done using whatever import hooks are installed in the current - environment, e.g. by "rexec". + environment. A dummy list ["__doc__"] is passed as the 4th argument so that e.g. PyImport_Import(PyUnicode_FromString("win32com.client.gencache")) will return <module "gencache"> instead of <module "win32com">. */ @@ -2753,6 +3022,7 @@ PyImport_Import(PyObject *module_name) PyObject *globals = NULL; PyObject *import = NULL; PyObject *builtins = NULL; + PyObject *modules = NULL; PyObject *r = NULL; /* Initialize constant string objects */ @@ -2763,7 +3033,7 @@ PyImport_Import(PyObject *module_name) builtins_str = PyUnicode_InternFromString("__builtins__"); if (builtins_str == NULL) return NULL; - silly_list = Py_BuildValue("[s]", "__doc__"); + silly_list = PyList_New(0); if (silly_list == NULL) return NULL; } @@ -2799,9 +3069,18 @@ PyImport_Import(PyObject *module_name) goto err; /* Call the __import__ function with the proper argument list - * Always use absolute import here. */ + Always use absolute import here. + Calling for side-effect of import. */ r = PyObject_CallFunction(import, "OOOOi", module_name, globals, globals, silly_list, 0, NULL); + if (r == NULL) + goto err; + Py_DECREF(r); + + modules = PyImport_GetModuleDict(); + r = PyDict_GetItem(modules, module_name); + if (r != NULL) + Py_INCREF(r); err: Py_XDECREF(globals); @@ -2817,19 +3096,31 @@ PyImport_Import(PyObject *module_name) */ static PyObject * -imp_get_magic(PyObject *self, PyObject *noargs) +imp_make_magic(long magic) { char buf[4]; - buf[0] = (char) ((pyc_magic >> 0) & 0xff); - buf[1] = (char) ((pyc_magic >> 8) & 0xff); - buf[2] = (char) ((pyc_magic >> 16) & 0xff); - buf[3] = (char) ((pyc_magic >> 24) & 0xff); + buf[0] = (char) ((magic >> 0) & 0xff); + buf[1] = (char) ((magic >> 8) & 0xff); + buf[2] = (char) ((magic >> 16) & 0xff); + buf[3] = (char) ((magic >> 24) & 0xff); return PyBytes_FromStringAndSize(buf, 4); } static PyObject * +imp_get_magic(PyObject *self, PyObject *noargs) +{ + return imp_make_magic(pyc_magic); +} + +static PyObject * +imp_get_tag(PyObject *self, PyObject *noargs) +{ + return PyUnicode_FromString(pyc_tag); +} + +static PyObject * imp_get_suffixes(PyObject *self, PyObject *noargs) { PyObject *list; @@ -2915,14 +3206,14 @@ call_find_module(char *name, PyObject *path) static PyObject * imp_find_module(PyObject *self, PyObject *args) { - char *name; + PyObject *name; PyObject *ret, *path = NULL; - if (!PyArg_ParseTuple(args, "es|O:find_module", - Py_FileSystemDefaultEncoding, &name, + if (!PyArg_ParseTuple(args, "O&|O:find_module", + PyUnicode_FSConverter, &name, &path)) return NULL; - ret = call_find_module(name, path); - PyMem_Free(name); + ret = call_find_module(PyBytes_AS_STRING(name), path); + Py_DECREF(name); return ret; } @@ -3040,23 +3331,23 @@ static PyObject * imp_load_compiled(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_compiled", + if (!PyArg_ParseTuple(args, "sO&|O:load_compiled", &name, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "rb"); + fp = get_file(PyBytes_AS_STRING(pathname), fob, "rb"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } - m = load_compiled_module(name, pathname, fp); + m = load_compiled_module(name, PyBytes_AS_STRING(pathname), fp); fclose(fp); - PyMem_Free(pathname); + Py_DECREF(pathname); return m; } @@ -3066,24 +3357,24 @@ static PyObject * imp_load_dynamic(PyObject *self, PyObject *args) { char *name; + PyObject *pathbytes; char *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp = NULL; - if (!PyArg_ParseTuple(args, "ses|O:load_dynamic", - &name, - Py_FileSystemDefaultEncoding, &pathname, - &fob)) + if (!PyArg_ParseTuple(args, "sO&|O:load_dynamic", + &name, PyUnicode_FSConverter, &pathbytes, &fob)) return NULL; + pathname = PyBytes_AS_STRING(pathbytes); if (fob) { fp = get_file(pathname, fob, "r"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathbytes); return NULL; } } m = _PyImport_LoadDynamicModule(name, pathname, fp); - PyMem_Free(pathname); + Py_DECREF(pathbytes); if (fp) fclose(fp); return m; @@ -3095,22 +3386,22 @@ static PyObject * imp_load_source(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "ses|O:load_source", + if (!PyArg_ParseTuple(args, "sO&|O:load_source", &name, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &fob)) return NULL; - fp = get_file(pathname, fob, "r"); + fp = get_file(PyBytes_AS_STRING(pathname), fob, "r"); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } - m = load_source_module(name, pathname, fp); - PyMem_Free(pathname); + m = load_source_module(name, PyBytes_AS_STRING(pathname), fp); + Py_DECREF(pathname); fclose(fp); return m; } @@ -3120,16 +3411,16 @@ imp_load_module(PyObject *self, PyObject *args) { char *name; PyObject *fob; - char *pathname; + PyObject *pathname; PyObject * ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOes(ssi):load_module", + if (!PyArg_ParseTuple(args, "sOO&(ssi):load_module", &name, &fob, - Py_FileSystemDefaultEncoding, &pathname, + PyUnicode_FSConverter, &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3140,7 +3431,7 @@ imp_load_module(PyObject *self, PyObject *args) if (!(*mode == 'r' || *mode == 'U') || strchr(mode, '+')) { PyErr_Format(PyExc_ValueError, "invalid file open mode %.200s", mode); - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } } @@ -3149,12 +3440,12 @@ imp_load_module(PyObject *self, PyObject *args) else { fp = get_file(NULL, fob, mode); if (fp == NULL) { - PyMem_Free(pathname); + Py_DECREF(pathname); return NULL; } } - ret = load_module(name, fp, pathname, type, NULL); - PyMem_Free(pathname); + ret = load_module(name, fp, PyBytes_AS_STRING(pathname), type, NULL); + Py_DECREF(pathname); if (fp) fclose(fp); return ret; @@ -3164,13 +3455,13 @@ static PyObject * imp_load_package(PyObject *self, PyObject *args) { char *name; - char *pathname; + PyObject *pathname; PyObject * ret; - if (!PyArg_ParseTuple(args, "ses:load_package", - &name, Py_FileSystemDefaultEncoding, &pathname)) + if (!PyArg_ParseTuple(args, "sO&:load_package", + &name, PyUnicode_FSConverter, &pathname)) return NULL; - ret = load_package(name, pathname); - PyMem_Free(pathname); + ret = load_package(name, PyBytes_AS_STRING(pathname)); + Py_DECREF(pathname); return ret; } @@ -3194,6 +3485,82 @@ PyDoc_STRVAR(doc_reload, \n\ Reload the module. The module must have been successfully imported before."); +static PyObject * +imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) +{ + static char *kwlist[] = {"path", "debug_override", NULL}; + + char buf[MAXPATHLEN+1]; + PyObject *pathbytes; + char *cpathname; + PyObject *debug_override = NULL; + int debug = !Py_OptimizeFlag; + + if (!PyArg_ParseTupleAndKeywords( + args, kws, "O&|O", kwlist, + PyUnicode_FSConverter, &pathbytes, &debug_override)) + return NULL; + + if (debug_override != NULL && + (debug = PyObject_IsTrue(debug_override)) < 0) { + Py_DECREF(pathbytes); + return NULL; + } + + cpathname = make_compiled_pathname( + PyBytes_AS_STRING(pathbytes), + buf, MAXPATHLEN+1, debug); + Py_DECREF(pathbytes); + + if (cpathname == NULL) { + PyErr_Format(PyExc_SystemError, "path buffer too short"); + return NULL; + } + return PyUnicode_DecodeFSDefault(buf); +} + +PyDoc_STRVAR(doc_cache_from_source, +"Given the path to a .py file, return the path to its .pyc/.pyo file.\n\ +\n\ +The .py file does not need to exist; this simply returns the path to the\n\ +.pyc/.pyo file calculated as if the .py file were imported. The extension\n\ +will be .pyc unless __debug__ is not defined, then it will be .pyo.\n\ +\n\ +If debug_override is not None, then it must be a boolean and is taken as\n\ +the value of __debug__ instead."); + +static PyObject * +imp_source_from_cache(PyObject *self, PyObject *args, PyObject *kws) +{ + static char *kwlist[] = {"path", NULL}; + + PyObject *pathname_obj; + char *pathname; + char buf[MAXPATHLEN+1]; + + if (!PyArg_ParseTupleAndKeywords( + args, kws, "O&", kwlist, + PyUnicode_FSConverter, &pathname_obj)) + return NULL; + + pathname = PyBytes_AS_STRING(pathname_obj); + if (make_source_pathname(pathname, buf) == NULL) { + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %s", + pathname); + Py_DECREF(pathname_obj); + return NULL; + } + Py_DECREF(pathname_obj); + return PyUnicode_FromString(buf); +} + +PyDoc_STRVAR(doc_source_from_cache, +"Given the path to a .pyc./.pyo file, return the path to its .py file.\n\ +\n\ +The .pyc/.pyo file does not need to exist; this simply returns the path to\n\ +the .py file calculated to correspond to the .pyc/.pyo file. If path\n\ +does not conform to PEP 3147 format, ValueError will be raised."); + /* Doc strings */ PyDoc_STRVAR(doc_imp, @@ -3216,6 +3583,10 @@ PyDoc_STRVAR(doc_get_magic, "get_magic() -> string\n\ Return the magic number for .pyc or .pyo files."); +PyDoc_STRVAR(doc_get_tag, +"get_tag() -> string\n\ +Return the magic tag for .pyc or .pyo files."); + PyDoc_STRVAR(doc_get_suffixes, "get_suffixes() -> [(suffix, mode, type), ...]\n\ Return a list of (suffix, mode, type) tuples describing the files\n\ @@ -3246,6 +3617,7 @@ On platforms without threads, this function does nothing."); static PyMethodDef imp_methods[] = { {"find_module", imp_find_module, METH_VARARGS, doc_find_module}, {"get_magic", imp_get_magic, METH_NOARGS, doc_get_magic}, + {"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag}, {"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes}, {"load_module", imp_load_module, METH_VARARGS, doc_load_module}, {"new_module", imp_new_module, METH_VARARGS, doc_new_module}, @@ -3253,6 +3625,10 @@ static PyMethodDef imp_methods[] = { {"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock}, {"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock}, {"reload", imp_reload, METH_O, doc_reload}, + {"cache_from_source", (PyCFunction)imp_cache_from_source, + METH_VARARGS | METH_KEYWORDS, doc_cache_from_source}, + {"source_from_cache", (PyCFunction)imp_source_from_cache, + METH_VARARGS | METH_KEYWORDS, doc_source_from_cache}, /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, METH_VARARGS}, {"is_frozen_package", imp_is_frozen_package, METH_VARARGS}, @@ -3288,56 +3664,69 @@ typedef struct { static int NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) { - char *path; - Py_ssize_t pathlen; +#ifndef MS_WINDOWS + PyObject *path; + struct stat statbuf; + int rv; if (!_PyArg_NoKeywords("NullImporter()", kwds)) return -1; - if (!PyArg_ParseTuple(args, "es:NullImporter", - Py_FileSystemDefaultEncoding, &path)) + if (!PyArg_ParseTuple(args, "O&:NullImporter", + PyUnicode_FSConverter, &path)) return -1; - pathlen = strlen(path); - if (pathlen == 0) { - PyMem_Free(path); + if (PyBytes_GET_SIZE(path) == 0) { + Py_DECREF(path); PyErr_SetString(PyExc_ImportError, "empty pathname"); return -1; - } else { -#ifndef MS_WINDOWS - struct stat statbuf; - int rv; - - rv = stat(path, &statbuf); - PyMem_Free(path); - if (rv == 0) { - /* it exists */ - if (S_ISDIR(statbuf.st_mode)) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } + } + + rv = stat(PyBytes_AS_STRING(path), &statbuf); + Py_DECREF(path); + if (rv == 0) { + /* it exists */ + if (S_ISDIR(statbuf.st_mode)) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, "existing directory"); + return -1; } + } #else /* MS_WINDOWS */ - DWORD rv; - /* see issue1293 and issue3677: - * stat() on Windows doesn't recognise paths like - * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. - */ - rv = GetFileAttributesA(path); - PyMem_Free(path); - if (rv != INVALID_FILE_ATTRIBUTES) { - /* it exists */ - if (rv & FILE_ATTRIBUTE_DIRECTORY) { - /* it's a directory */ - PyErr_SetString(PyExc_ImportError, - "existing directory"); - return -1; - } + PyObject *pathobj; + DWORD rv; + wchar_t *path; + + if (!_PyArg_NoKeywords("NullImporter()", kwds)) + return -1; + + if (!PyArg_ParseTuple(args, "U:NullImporter", + &pathobj)) + return -1; + + if (PyUnicode_GET_SIZE(pathobj) == 0) { + PyErr_SetString(PyExc_ImportError, "empty pathname"); + return -1; + } + + path = PyUnicode_AsWideCharString(pathobj, NULL); + if (path == NULL) + return -1; + /* see issue1293 and issue3677: + * stat() on Windows doesn't recognise paths like + * "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. + */ + rv = GetFileAttributesW(path); + PyMem_Free(path); + if (rv != INVALID_FILE_ATTRIBUTES) { + /* it exists */ + if (rv & FILE_ATTRIBUTE_DIRECTORY) { + /* it's a directory */ + PyErr_SetString(PyExc_ImportError, "existing directory"); + return -1; } -#endif } +#endif return 0; } @@ -3440,7 +3829,6 @@ PyInit_imp(void) failure: Py_XDECREF(m); return NULL; - } |