From 313459bc23e59254ad32059385f99cb0d80feecb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Feb 2011 21:05:50 +0000 Subject: Remove filename variable from ceval.c Issue #11168: Remove filename debug variable from PyEval_EvalFrameEx(). It encoded the Unicode filename to UTF-8, but the encoding fails on undecodable filename (on surrogate characters) which raises an unexpected UnicodeEncodeError on recursion limit. --- Python/ceval.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index f6d4b0b84b..c10a2ff594 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -811,10 +811,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) unsigned char *first_instr; PyObject *names; PyObject *consts; -#if defined(Py_DEBUG) || defined(LLTRACE) - /* Make it easier to find out where we are with a debugger */ - char *filename; -#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -1227,18 +1223,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #ifdef LLTRACE lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; #endif -#if defined(Py_DEBUG) || defined(LLTRACE) - { - PyObject *error_type, *error_value, *error_traceback; - PyErr_Fetch(&error_type, &error_value, &error_traceback); - filename = _PyUnicode_AsString(co->co_filename); - if (filename == NULL && tstate->overflowed) { - /* maximum recursion depth exceeded */ - goto exit_eval_frame; - } - PyErr_Restore(error_type, error_value, error_traceback); - } -#endif why = WHY_NOT; err = 0; -- cgit v1.2.1 From ffbf24bf0cc297d080d6d68bc809a9c156c49123 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Tue, 22 Feb 2011 20:15:44 +0000 Subject: Issue #8914: fix various warnings from the Clang static analyzer v254. --- Python/ast.c | 1 - Python/bltinmodule.c | 5 +---- Python/ceval.c | 4 ++-- Python/dtoa.c | 4 ++-- Python/getargs.c | 5 ++--- Python/pystrtod.c | 2 +- Python/sysmodule.c | 3 +-- 7 files changed, 9 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 4edf335c33..e62a2156b7 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3231,7 +3231,6 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons const char *end; if (encoding == NULL) { - buf = (char *)s; u = NULL; } else { /* check for integer overflow */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f9b3202d54..42bc8091e1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -37,7 +37,7 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *func, *name, *bases, *mkw, *meta, *prep, *ns, *cell; PyObject *cls = NULL; - Py_ssize_t nargs, nbases; + Py_ssize_t nargs; assert(args != NULL); if (!PyTuple_Check(args)) { @@ -61,7 +61,6 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) bases = PyTuple_GetSlice(args, 2, nargs); if (bases == NULL) return NULL; - nbases = nargs - 2; if (kwds == NULL) { meta = NULL; @@ -766,7 +765,6 @@ builtin_exec(PyObject *self, PyObject *args) { PyObject *v; PyObject *prog, *globals = Py_None, *locals = Py_None; - int plain = 0; if (!PyArg_UnpackTuple(args, "exec", 1, 3, &prog, &globals, &locals)) return NULL; @@ -775,7 +773,6 @@ builtin_exec(PyObject *self, PyObject *args) globals = PyEval_GetGlobals(); if (locals == Py_None) { locals = PyEval_GetLocals(); - plain = 1; } if (!globals || !locals) { PyErr_SetString(PyExc_SystemError, diff --git a/Python/ceval.c b/Python/ceval.c index c10a2ff594..9572918dc3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2690,7 +2690,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(*pfunc); *pfunc = self; na++; - n++; + /* n++; */ } else Py_INCREF(func); sp = stack_pointer; @@ -3026,7 +3026,7 @@ fast_yield: PyTrace_RETURN, retval)) { Py_XDECREF(retval); retval = NULL; - why = WHY_EXCEPTION; + /* why = WHY_EXCEPTION; */ } } } diff --git a/Python/dtoa.c b/Python/dtoa.c index 44dc01f1d5..82b6faa80c 100644 --- a/Python/dtoa.c +++ b/Python/dtoa.c @@ -2055,7 +2055,7 @@ _Py_dg_strtod(const char *s00, char **se) + Exp_msk1 ; word1(&rv) = 0; - dsign = 0; + /* dsign = 0; */ break; } } @@ -2092,7 +2092,7 @@ _Py_dg_strtod(const char *s00, char **se) goto undfl; } } - dsign = 1 - dsign; + /* dsign = 1 - dsign; */ break; } if ((aadj = ratio(delta, bs)) <= 2.) { diff --git a/Python/getargs.c b/Python/getargs.c index 600941d9c7..17d5993c8a 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -966,9 +966,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'u': /* raw unicode buffer (Py_UNICODE *) */ case 'Z': /* raw unicode buffer or None */ { + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + if (*format == '#') { /* any buffer-like object */ /* "s#" or "Z#" */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); FETCH_SIZE; if (c == 'Z' && arg == Py_None) { @@ -984,8 +985,6 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, format++; } else { /* "s" or "Z" */ - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - if (c == 'Z' && arg == Py_None) *p = NULL; else if (PyUnicode_Check(arg)) { diff --git a/Python/pystrtod.c b/Python/pystrtod.c index 75e3032fb7..7bf21c0bc1 100644 --- a/Python/pystrtod.c +++ b/Python/pystrtod.c @@ -954,7 +954,7 @@ format_float_short(double d, char format_code, /* shouldn't get here: Gay's code should always return something starting with a digit, an 'I', or 'N' */ strncpy(p, "ERR", 3); - p += 3; + /* p += 3; */ assert(0); } goto exit; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index de51155a49..89fe4f1fe6 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1176,7 +1176,6 @@ PySys_AddXOption(const wchar_t *s) PyObject *opts; PyObject *name = NULL, *value = NULL; const wchar_t *name_end; - int r; opts = get_xoptions(); if (opts == NULL) @@ -1194,7 +1193,7 @@ PySys_AddXOption(const wchar_t *s) } if (name == NULL || value == NULL) goto error; - r = PyDict_SetItem(opts, name, value); + PyDict_SetItem(opts, name, value); Py_DECREF(name); Py_DECREF(value); return; -- cgit v1.2.1 From b5162583f02ef19edb3b4804cac793f1183c6283 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Feb 2011 23:12:28 +0000 Subject: Issue #3080: Mark PyWin_FindRegisteredModule() as private This function was not declared in Python public API (in any .h file) and not documented. Mark it as private to prepare a change of its API. --- Python/import.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 23752eeb72..f4015b52fa 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1547,8 +1547,8 @@ PyImport_GetImporter(PyObject *path) { pathname and an open file. Return NULL if the module is not found. */ #ifdef MS_COREDLL -extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **, - char *, Py_ssize_t); +extern FILE *_PyWin_FindRegisteredModule(const char *, struct filedescr **, + char *, Py_ssize_t); #endif static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); @@ -1631,7 +1631,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, return &fd_builtin; } #ifdef MS_COREDLL - fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); + fp = _PyWin_FindRegisteredModule(name, &fdp, buf, buflen); if (fp != NULL) { *p_fp = fp; return fdp; -- cgit v1.2.1 From 3046647478f584b665a33c3a1c3d1d6117979d64 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Feb 2011 23:16:19 +0000 Subject: Issue #3080: Remove unused argument of _PyImport_GetDynLoadFunc() The first argument, fqname, was not used. --- Python/dynload_aix.c | 2 +- Python/dynload_dl.c | 2 +- Python/dynload_hpux.c | 2 +- Python/dynload_next.c | 4 ++-- Python/dynload_os2.c | 2 +- Python/dynload_shlib.c | 2 +- Python/dynload_win.c | 2 +- Python/importdl.c | 5 ++--- 8 files changed, 10 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c index 149990d799..74c7b32603 100644 --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -154,7 +154,7 @@ aix_loaderror(const char *pathname) } -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c index 2606e1e32f..dc00ec5609 100644 --- a/Python/dynload_dl.c +++ b/Python/dynload_dl.c @@ -16,7 +16,7 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { }; -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { char funcname[258]; diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index 18a81377f2..3ebbbad01f 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -19,7 +19,7 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {0, 0} }; -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/dynload_next.c b/Python/dynload_next.c index cabf9b9663..eb17950b45 100644 --- a/Python/dynload_next.c +++ b/Python/dynload_next.c @@ -31,8 +31,8 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #define LINKOPTIONS NSLINKMODULE_OPTION_BINDNOW| \ NSLINKMODULE_OPTION_RETURN_ON_ERROR|NSLINKMODULE_OPTION_PRIVATE #endif -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, + const char *pathname, FILE *fp) { dl_funcptr p = NULL; char funcname[258]; diff --git a/Python/dynload_os2.c b/Python/dynload_os2.c index 101c024bbe..f7264da04c 100644 --- a/Python/dynload_os2.c +++ b/Python/dynload_os2.c @@ -15,7 +15,7 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {0, 0} }; -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 7ea510e862..1c215c329c 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -75,7 +75,7 @@ static struct { static int nhandles = 0; -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 73a1dcf897..9c04250f33 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -171,7 +171,7 @@ static char *GetPythonImport (HINSTANCE hModule) return NULL; } -dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, +dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p; diff --git a/Python/importdl.c b/Python/importdl.c index 9caed453aa..74ca8a7cca 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -12,8 +12,7 @@ #include "importdl.h" -extern dl_funcptr _PyImport_GetDynLoadFunc(const char *name, - const char *shortname, +extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp); @@ -48,7 +47,7 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) shortname = lastdot+1; } - p0 = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp); + p0 = _PyImport_GetDynLoadFunc(shortname, pathname, fp); p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) goto error; -- cgit v1.2.1 From 90268ce7e125f2d8a1d9b8f41b51d31f96b1c8fd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Feb 2011 00:02:00 +0000 Subject: Issue #3080: Mark _PyImport_FindBuiltin() argument as constant And as a consequence, mark also name argument of _PyImport_FindExtensionUnicode() constant too. But I plan to change this argument type to PyObject* later. --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index f4015b52fa..39cd93f7dd 100644 --- a/Python/import.c +++ b/Python/import.c @@ -636,7 +636,7 @@ _PyImport_FixupBuiltin(PyObject *mod, char *name) } PyObject * -_PyImport_FindExtensionUnicode(char *name, PyObject *filename) +_PyImport_FindExtensionUnicode(const char *name, PyObject *filename) { PyObject *mod, *mdict; PyModuleDef* def; @@ -680,7 +680,7 @@ _PyImport_FindExtensionUnicode(char *name, PyObject *filename) } PyObject * -_PyImport_FindBuiltin(char *name) +_PyImport_FindBuiltin(const char *name) { PyObject *res, *filename; filename = PyUnicode_FromString(name); -- cgit v1.2.1 From 05114f1fbe912fc623d3c45cc34f983ab0b3c954 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Feb 2011 11:29:28 +0000 Subject: dynload_dl.c: replace tabs by spaces --- Python/dynload_dl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c index dc00ec5609..37519b23e7 100644 --- a/Python/dynload_dl.c +++ b/Python/dynload_dl.c @@ -10,17 +10,17 @@ extern char *Py_GetProgramName(void); const struct filedescr _PyImport_DynLoadFiletab[] = { - {".o", "rb", C_EXTENSION}, - {"module.o", "rb", C_EXTENSION}, - {0, 0} + {".o", "rb", C_EXTENSION}, + {"module.o", "rb", C_EXTENSION}, + {0, 0} }; dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) + const char *pathname, FILE *fp) { - char funcname[258]; + char funcname[258]; - PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); - return dl_loadmod(Py_GetProgramName(), pathname, funcname); + PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); + return dl_loadmod(Py_GetProgramName(), pathname, funcname); } -- cgit v1.2.1 From 8d4acf67131b9a1241bbda784905c5730c382d60 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 Feb 2011 12:07:37 +0000 Subject: Issue #11272: Fix input() and sys.stdin for Windows newline On Windows, input() strips '\r' (and not only '\n'), and sys.stdin uses universal newline (replace '\r\n' by '\n'). --- Python/bltinmodule.c | 13 +++++++++---- Python/pythonrun.c | 11 ++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 42bc8091e1..c6bb16c4e1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1618,6 +1618,7 @@ builtin_input(PyObject *self, PyObject *args) PyObject *stdin_encoding; char *stdin_encoding_str; PyObject *result; + size_t len; stdin_encoding = PyObject_GetAttrString(fin, "encoding"); if (!stdin_encoding) @@ -1682,19 +1683,23 @@ builtin_input(PyObject *self, PyObject *args) Py_DECREF(stdin_encoding); return NULL; } - if (*s == '\0') { + + len = strlen(s); + if (len == 0) { PyErr_SetNone(PyExc_EOFError); result = NULL; } - else { /* strip trailing '\n' */ - size_t len = strlen(s); + else { if (len > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "input: input too long"); result = NULL; } else { - result = PyUnicode_Decode(s, len-1, stdin_encoding_str, NULL); + len--; /* strip trailing '\n' */ + if (len != 0 && s[len-1] == '\r') + len--; /* strip trailing '\r' */ + result = PyUnicode_Decode(s, len, stdin_encoding_str, NULL); } } Py_DECREF(stdin_encoding); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 33f187386a..8e97d7fc24 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -778,6 +778,7 @@ create_stdio(PyObject* io, { PyObject *buf = NULL, *stream = NULL, *text = NULL, *raw = NULL, *res; const char* mode; + const char* newline; PyObject *line_buffering; int buffering, isatty; @@ -828,9 +829,17 @@ create_stdio(PyObject* io, Py_CLEAR(raw); Py_CLEAR(text); + newline = "\n"; +#ifdef MS_WINDOWS + if (!write_mode) { + /* translate \r\n to \n for sys.stdin on Windows */ + newline = NULL; + } +#endif + stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", buf, encoding, errors, - "\n", line_buffering); + newline, line_buffering); Py_CLEAR(buf); if (stream == NULL) goto error; -- cgit v1.2.1 From 4f56cb4c86c3b5ea71e14326dd3fe8aa0e447a34 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 2 Mar 2011 01:03:11 +0000 Subject: Remove useless argument of _PyUnicode_AsDefaultEncodedString() --- Python/bltinmodule.c | 2 +- Python/compile.c | 2 +- Python/getargs.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c6bb16c4e1..ca40cb07dc 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -511,7 +511,7 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) if (PyUnicode_Check(cmd)) { cf->cf_flags |= PyCF_IGNORE_COOKIE; - cmd = _PyUnicode_AsDefaultEncodedString(cmd, NULL); + cmd = _PyUnicode_AsDefaultEncodedString(cmd); if (cmd == NULL) return NULL; } diff --git a/Python/compile.c b/Python/compile.c index 1d6e38c22e..53f5a12cc3 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3026,7 +3026,7 @@ expr_constant(struct compiler *c, expr_ty e) case Name_kind: /* optimize away names that can't be reassigned */ id = PyBytes_AS_STRING( - _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL)); + _PyUnicode_AsDefaultEncodedString(e->v.Name.id)); if (strcmp(id, "True") == 0) return 1; if (strcmp(id, "False") == 0) return 0; if (strcmp(id, "None") == 0) return 0; diff --git a/Python/getargs.c b/Python/getargs.c index 17d5993c8a..e1cef0cc58 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -551,7 +551,7 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, #define UNICODE_DEFAULT_ENCODING(arg) \ - _PyUnicode_AsDefaultEncodedString(arg, NULL) + _PyUnicode_AsDefaultEncodedString(arg) /* Format an error message generated by convertsimple(). */ -- cgit v1.2.1 From b05cc9bc8518f72fcb3e33b764f24dae32d5524f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 4 Mar 2011 12:57:09 +0000 Subject: Issue #3080: Add PyImport_AddModuleObject() and PyImport_ExecCodeModuleObject() --- Python/import.c | 87 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 21 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 39cd93f7dd..22a7c8744d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -698,18 +698,18 @@ _PyImport_FindBuiltin(const char *name) 'NEW' REFERENCE! */ PyObject * -PyImport_AddModule(const char *name) +PyImport_AddModuleObject(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m; - if ((m = PyDict_GetItemString(modules, name)) != NULL && + if ((m = PyDict_GetItem(modules, name)) != NULL && PyModule_Check(m)) return m; - m = PyModule_New(name); + m = PyModule_NewObject(name); if (m == NULL) return NULL; - if (PyDict_SetItemString(modules, name, m) != 0) { + if (PyDict_SetItem(modules, name, m) != 0) { Py_DECREF(m); return NULL; } @@ -718,14 +718,27 @@ PyImport_AddModule(const char *name) return m; } +PyObject * +PyImport_AddModule(const char *name) +{ + PyObject *nameobj, *module; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + module = PyImport_AddModuleObject(nameobj); + Py_DECREF(nameobj); + return module; +} + + /* Remove name from sys.modules, if it's there. */ static void -remove_module(const char *name) +remove_module(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - if (PyDict_GetItemString(modules, name) == NULL) + if (PyDict_GetItem(modules, name) == NULL) return; - if (PyDict_DelItemString(modules, name) < 0) + if (PyDict_DelItem(modules, name) < 0) Py_FatalError("import: deleting existing key in" "sys.modules failed"); } @@ -762,11 +775,43 @@ PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname) PyObject * PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, char *cpathname) +{ + PyObject *m = NULL; + PyObject *nameobj, *pathobj = NULL, *cpathobj = NULL; + + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + + if (pathname != NULL) { + pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) + goto error; + } else + pathobj = NULL; + if (cpathname != NULL) { + cpathobj = PyUnicode_DecodeFSDefault(cpathname); + if (cpathobj == NULL) + goto error; + } else + cpathobj = NULL; + m = PyImport_ExecCodeModuleObject(nameobj, co, pathobj, cpathobj); +error: + Py_DECREF(nameobj); + Py_XDECREF(pathobj); + Py_XDECREF(cpathobj); + return m; +} + +PyObject* +PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, + PyObject *cpathname) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; + PyObject *pathbytes; - m = PyImport_AddModule(name); + m = PyImport_AddModuleObject(name); if (m == NULL) return NULL; /* If the module is being reloaded, we get the old module back @@ -778,12 +823,18 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, goto error; } /* Remember the filename as the __file__ attribute */ - v = NULL; if (pathname != NULL) { - v = get_sourcefile(pathname); + pathbytes = PyUnicode_EncodeFSDefault(pathname); + if (pathbytes != NULL) { + v = get_sourcefile(PyBytes_AS_STRING(pathbytes)); + Py_DECREF(pathbytes); + } else + v = NULL; if (v == NULL) PyErr_Clear(); } + else + v = NULL; if (v == NULL) { v = ((PyCodeObject *)co)->co_filename; Py_INCREF(v); @@ -793,27 +844,21 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname, Py_DECREF(v); /* 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 */ + if (cpathname != NULL) + v = cpathname; + else 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); - if ((m = PyDict_GetItemString(modules, name)) == NULL) { + if ((m = PyDict_GetItem(modules, name)) == NULL) { PyErr_Format(PyExc_ImportError, - "Loaded module %.200s not found in sys.modules", + "Loaded module %R not found in sys.modules", name); return NULL; } -- cgit v1.2.1 From 5db419fc1fe185b5ada72ff88056bc21e1d70c01 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 6 Mar 2011 10:35:42 +0100 Subject: Remove sys.subversion and svn build identification leftovers. --- Python/sysmodule.c | 94 ------------------------------------------------------ 1 file changed, 94 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 9c94ececd5..d06adc0aca 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1255,7 +1255,6 @@ int_info -- a struct sequence with information about the int implementation.\n\ maxsize -- the largest supported length of containers.\n\ maxunicode -- the largest supported character\n\ builtin_module_names -- tuple of module names built into this interpreter\n\ -subversion -- subversion information of the build as tuple\n\ version -- the version of this interpreter as a string\n\ version_info -- version information as a named tuple\n\ hexversion -- version information encoded as a single integer\n\ @@ -1303,95 +1302,6 @@ settrace() -- set the global debug tracing function\n\ ) /* end of sys_doc */ ; -/* Subversion branch and revision management */ -static const char _patchlevel_revision[] = PY_PATCHLEVEL_REVISION; -static const char headurl[] = "$HeadURL$"; -static int svn_initialized; -static char patchlevel_revision[50]; /* Just the number */ -static char branch[50]; -static char shortbranch[50]; -static const char *svn_revision; - -static void -svnversion_init(void) -{ - const char *python, *br_start, *br_end, *br_end2, *svnversion; - Py_ssize_t len; - int istag = 0; - - if (svn_initialized) - return; - - python = strstr(headurl, "/python/"); - if (!python) { - strcpy(branch, "unknown branch"); - strcpy(shortbranch, "unknown"); - } - else { - br_start = python + 8; - br_end = strchr(br_start, '/'); - assert(br_end); - - /* Works even for trunk, - as we are in trunk/Python/sysmodule.c */ - br_end2 = strchr(br_end+1, '/'); - - istag = strncmp(br_start, "tags", 4) == 0; - if (strncmp(br_start, "trunk", 5) == 0) { - strcpy(branch, "trunk"); - strcpy(shortbranch, "trunk"); - } - else if (istag || strncmp(br_start, "branches", 8) == 0) { - len = br_end2 - br_start; - strncpy(branch, br_start, len); - branch[len] = '\0'; - - len = br_end2 - (br_end + 1); - strncpy(shortbranch, br_end + 1, len); - shortbranch[len] = '\0'; - } - else { - Py_FatalError("bad HeadURL"); - return; - } - } - - - svnversion = _Py_svnversion(); - if (strcmp(svnversion, "Unversioned directory") != 0 && strcmp(svnversion, "exported") != 0) - svn_revision = svnversion; - else if (istag) { - len = strlen(_patchlevel_revision); - assert(len >= 13); - assert(len < (sizeof(patchlevel_revision) + 13)); - strncpy(patchlevel_revision, _patchlevel_revision + 11, - len - 13); - patchlevel_revision[len - 13] = '\0'; - svn_revision = patchlevel_revision; - } - else - svn_revision = ""; - - svn_initialized = 1; -} - -/* Return svnversion output if available. - Else return Revision of patchlevel.h if on branch. - Else return empty string */ -const char* -Py_SubversionRevision() -{ - svnversion_init(); - return svn_revision; -} - -const char* -Py_SubversionShortBranch() -{ - svnversion_init(); - return shortbranch; -} - PyDoc_STRVAR(flags__doc__, "sys.flags\n\ @@ -1595,10 +1505,6 @@ _PySys_Init(void) PyUnicode_FromString(Py_GetVersion())); SET_SYS_FROM_STRING("hexversion", PyLong_FromLong(PY_VERSION_HEX)); - svnversion_init(); - SET_SYS_FROM_STRING("subversion", - Py_BuildValue("(sss)", "CPython", branch, - svn_revision)); SET_SYS_FROM_STRING("_mercurial", Py_BuildValue("(szz)", "CPython", _Py_hgidentifier(), _Py_hgversion())); -- cgit v1.2.1 From 3d8cfd2a2d24b44aab6eafa4e1293508b45d7eec Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 11 Mar 2011 17:27:02 +0100 Subject: Issue #11244: The peephole optimizer is now able to constant-fold arbitrarily complex expressions. This also fixes a 3.2 regression where operations involving negative numbers were not constant-folded. --- Python/peephole.c | 167 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 47 deletions(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index f972e1611e..ab96ce9def 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -23,6 +23,64 @@ #define ISBASICBLOCK(blocks, start, bytes) \ (blocks[start]==blocks[start+bytes-1]) + +#define CONST_STACK_CREATE() { \ + const_stack_size = 256; \ + const_stack = PyMem_New(PyObject *, const_stack_size); \ + load_const_stack = PyMem_New(Py_ssize_t, const_stack_size); \ + if (!const_stack || !load_const_stack) { \ + PyErr_NoMemory(); \ + goto exitError; \ + } \ + } + +#define CONST_STACK_DELETE() do { \ + if (const_stack) \ + PyMem_Free(const_stack); \ + if (load_const_stack) \ + PyMem_Free(load_const_stack); \ + } while(0) + +#define CONST_STACK_LEN() (const_stack_top + 1) + +#define CONST_STACK_PUSH_OP(i) do { \ + PyObject *_x; \ + assert(codestr[i] == LOAD_CONST); \ + assert(PyList_GET_SIZE(consts) > GETARG(codestr, i)); \ + _x = PyList_GET_ITEM(consts, GETARG(codestr, i)); \ + if (++const_stack_top >= const_stack_size) { \ + const_stack_size *= 2; \ + PyMem_Resize(const_stack, PyObject *, const_stack_size); \ + PyMem_Resize(load_const_stack, Py_ssize_t, const_stack_size); \ + if (!const_stack || !load_const_stack) { \ + PyErr_NoMemory(); \ + goto exitError; \ + } \ + } \ + load_const_stack[const_stack_top] = i; \ + const_stack[const_stack_top] = _x; \ + in_consts = 1; \ + } while(0) + +#define CONST_STACK_RESET() do { \ + const_stack_top = -1; \ + } while(0) + +#define CONST_STACK_TOP(x) \ + const_stack[const_stack_top] + +#define CONST_STACK_LASTN(i) \ + &const_stack[const_stack_top - i + 1] + +#define CONST_STACK_POP(i) do { \ + assert(const_stack_top + 1 >= i); \ + const_stack_top -= i; \ + } while(0) + +#define CONST_STACK_OP_LASTN(i) \ + ((const_stack_top >= i - 1) ? load_const_stack[const_stack_top - i + 1] : -1) + + /* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_TUPLE n with LOAD_CONST (c1, c2, ... cn). The consts table must still be in list form so that the @@ -33,17 +91,14 @@ test; for BUILD_SET it assembles a frozenset rather than a tuple. */ static int -tuple_of_constants(unsigned char *codestr, Py_ssize_t n, PyObject *consts) +tuple_of_constants(unsigned char *codestr, Py_ssize_t n, + PyObject *consts, PyObject **objs) { PyObject *newconst, *constant; - Py_ssize_t i, arg, len_consts; + Py_ssize_t i, len_consts; /* Pre-conditions */ assert(PyList_CheckExact(consts)); - assert(codestr[n*3] == BUILD_TUPLE || codestr[n*3] == BUILD_LIST || codestr[n*3] == BUILD_SET); - assert(GETARG(codestr, (n*3)) == n); - for (i=0 ; i= 0 && - j <= lastlc && + if (j == 0) + break; + h = CONST_STACK_OP_LASTN(j); + assert((h >= 0 || CONST_STACK_LEN() < j)); + if (h >= 0 && j > 0 && j <= CONST_STACK_LEN() && ((opcode == BUILD_TUPLE && - ISBASICBLOCK(blocks, h, 3*(j+1))) || + ISBASICBLOCK(blocks, h, i-h+3)) || ((opcode == BUILD_LIST || opcode == BUILD_SET) && codestr[i+3]==COMPARE_OP && - ISBASICBLOCK(blocks, h, 3*(j+2)) && + ISBASICBLOCK(blocks, h, i-h+6) && (GETARG(codestr,i+3)==6 || GETARG(codestr,i+3)==7))) && - tuple_of_constants(&codestr[h], j, consts)) { + tuple_of_constants(&codestr[i], j, consts, CONST_STACK_LASTN(j))) { assert(codestr[i] == LOAD_CONST); - cumlc = 1; + memset(&codestr[h], NOP, i - h); + CONST_STACK_POP(j); + CONST_STACK_PUSH_OP(i); break; } if (codestr[i+3] != UNPACK_SEQUENCE || @@ -482,10 +542,12 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } else if (j == 2) { codestr[i] = ROT_TWO; memset(codestr+i+1, NOP, 5); + CONST_STACK_RESET(); } else if (j == 3) { codestr[i] = ROT_THREE; codestr[i+1] = ROT_TWO; memset(codestr+i+2, NOP, 4); + CONST_STACK_RESET(); } break; @@ -504,12 +566,18 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case BINARY_AND: case BINARY_XOR: case BINARY_OR: - if (lastlc >= 2 && - ISBASICBLOCK(blocks, i-6, 7) && - fold_binops_on_constants(&codestr[i-6], consts)) { + /* NOTE: LOAD_CONST is saved at `i-2` since it has an arg + while BINOP hasn't */ + h = CONST_STACK_OP_LASTN(2); + assert((h >= 0 || CONST_STACK_LEN() < 2)); + if (h >= 0 && + ISBASICBLOCK(blocks, h, i-h+1) && + fold_binops_on_constants(&codestr[i], consts, CONST_STACK_LASTN(2))) { i -= 2; + memset(&codestr[h], NOP, i - h); assert(codestr[i] == LOAD_CONST); - cumlc = 1; + CONST_STACK_POP(2); + CONST_STACK_PUSH_OP(i); } break; @@ -518,12 +586,15 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case UNARY_NEGATIVE: case UNARY_INVERT: case UNARY_POSITIVE: - if (lastlc >= 1 && - ISBASICBLOCK(blocks, i-3, 4) && - fold_unaryops_on_constants(&codestr[i-3], consts)) { + h = CONST_STACK_OP_LASTN(1); + assert((h >= 0 || CONST_STACK_LEN() < 1)); + if (h >= 0 && + ISBASICBLOCK(blocks, h, i-h+1) && + fold_unaryops_on_constants(&codestr[i-3], consts, CONST_STACK_TOP())) { i -= 2; assert(codestr[i] == LOAD_CONST); - cumlc = 1; + CONST_STACK_POP(1); + CONST_STACK_PUSH_OP(i); } break; @@ -680,6 +751,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, assert(h + nops == codelen); code = PyBytes_FromStringAndSize((char *)codestr, h); + CONST_STACK_DELETE(); PyMem_Free(addrmap); PyMem_Free(codestr); PyMem_Free(blocks); @@ -689,6 +761,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, code = NULL; exitUnchanged: + CONST_STACK_DELETE(); if (blocks != NULL) PyMem_Free(blocks); if (addrmap != NULL) -- cgit v1.2.1 From 62af56412a8c773247c801ce4d6204067c629b9e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 12 Mar 2011 18:28:16 -0600 Subject: convert ast versioning to mercurial --- Python/Python-ast.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2c09f96f0e..726227cebb 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 82163. + __version__ 68409:c017695acf19. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6739,7 +6739,8 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "82163") < 0) + if (PyModule_AddStringConstant(m, "__version__", "68409:c017695acf19") + < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From a32ee4902fcf9c19d70af80a1ea840c7f10e1f24 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 12 Mar 2011 18:35:23 -0600 Subject: bump ast version --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 726227cebb..3150d104eb 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 68409:c017695acf19. + __version__ 68410:0daa6ba25d9b. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6739,7 +6739,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "68409:c017695acf19") + if (PyModule_AddStringConstant(m, "__version__", "68410:0daa6ba25d9b") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return -- cgit v1.2.1 From ae66aaa9e45d8e330acc895b04f183995c45016d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 13 Mar 2011 16:36:08 -0500 Subject: use only the hex version, since the revno is unreliable across repos --- Python/Python-ast.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 3150d104eb..6b1ea3cbab 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 68410:0daa6ba25d9b. + __version__ 0daa6ba25d9b. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6739,8 +6739,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "68410:0daa6ba25d9b") - < 0) + if (PyModule_AddStringConstant(m, "__version__", "0daa6ba25d9b") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From a4350798d054973b1c8a6cbfc54edd8ddbe416b6 Mon Sep 17 00:00:00 2001 From: Jesus Cea Date: Mon, 14 Mar 2011 17:36:54 +0100 Subject: Issue #11495: OSF support is eliminated. It was deprecated in Python 3.2 --- Python/thread_pth.h | 3 +-- Python/thread_pthread.h | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/thread_pth.h b/Python/thread_pth.h index 82a00e72ba..5704266a03 100644 --- a/Python/thread_pth.h +++ b/Python/thread_pth.h @@ -69,9 +69,8 @@ long PyThread_get_thread_ident(void) volatile pth_t threadid; if (!initialized) PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ threadid = pth_self(); - return (long) *(long *) &threadid; + return (long) threadid; } void PyThread_exit_thread(void) diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index ffc791c578..7d36b920b5 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -228,8 +228,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg) hosed" because: - It does not guarantee the promise that a non-zero integer is returned. - The cast to long is inherently unsafe. - - It is not clear that the 'volatile' (for AIX?) and ugly casting in the - latter return statement (for Alpha OSF/1) are any longer necessary. + - It is not clear that the 'volatile' (for AIX?) are any longer necessary. */ long PyThread_get_thread_ident(void) @@ -237,13 +236,8 @@ PyThread_get_thread_ident(void) volatile pthread_t threadid; if (!initialized) PyThread_init_thread(); - /* Jump through some hoops for Alpha OSF/1 */ threadid = pthread_self(); -#if SIZEOF_PTHREAD_T <= SIZEOF_LONG return (long) threadid; -#else - return (long) *(long *) &threadid; -#endif } void -- cgit v1.2.1 From 312c21bb172f56ba90c4c06e2873ceac1170aa18 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 15 Mar 2011 15:03:36 -0700 Subject: Issue 11510: Fix BUILD_SET optimizer bug. --- Python/peephole.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index ab96ce9def..4bc65dcc31 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -535,7 +535,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, } if (codestr[i+3] != UNPACK_SEQUENCE || !ISBASICBLOCK(blocks,i,6) || - j != GETARG(codestr, i+3)) + j != GETARG(codestr, i+3) || + opcode == BUILD_SET) continue; if (j == 1) { memset(codestr+i, NOP, 6); -- cgit v1.2.1 From 426e754b8e8cf35a60153914ae341ca57e9d5031 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 7 Mar 2011 16:57:48 +0100 Subject: import.c: replace tab by spaces --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 22a7c8744d..b2757dffdc 100644 --- a/Python/import.c +++ b/Python/import.c @@ -329,7 +329,7 @@ _PyImport_ReInitLock(void) /* 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? */ + /* XXX: can the previous line fail? */ import_lock_thread = me; import_lock_level--; } else { -- cgit v1.2.1 From 13abff792323d15e50b40c4ef978441790bef7b3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 7 Mar 2011 17:08:21 +0100 Subject: Issue #3080: PyImport_Cleanup() uses Unicode Replace strcmp() by PyUnicode_CompareWithASCIIString() --- Python/import.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b2757dffdc..9366be0589 100644 --- a/Python/import.c +++ b/Python/import.c @@ -418,7 +418,6 @@ void PyImport_Cleanup(void) { Py_ssize_t pos, ndone; - char *name; PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; @@ -491,14 +490,13 @@ PyImport_Cleanup(void) if (value->ob_refcnt != 1) continue; if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = _PyUnicode_AsString(key); - if (strcmp(name, "builtins") == 0) + if (PyUnicode_CompareWithASCIIString(key, "builtins") == 0) continue; - if (strcmp(name, "sys") == 0) + if (PyUnicode_CompareWithASCIIString(key, "sys") == 0) continue; if (Py_VerboseFlag) - PySys_WriteStderr( - "# cleanup[1] %s\n", name); + PySys_FormatStderr( + "# cleanup[1] %U\n", key); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); ndone++; @@ -510,13 +508,12 @@ PyImport_Cleanup(void) pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (PyUnicode_Check(key) && PyModule_Check(value)) { - name = _PyUnicode_AsString(key); - if (strcmp(name, "builtins") == 0) + if (PyUnicode_CompareWithASCIIString(key, "builtins") == 0) continue; - if (strcmp(name, "sys") == 0) + if (PyUnicode_CompareWithASCIIString(key, "sys") == 0) continue; if (Py_VerboseFlag) - PySys_WriteStderr("# cleanup[2] %s\n", name); + PySys_FormatStderr("# cleanup[2] %U\n", key); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); } -- cgit v1.2.1 From 46cbf15e71a6cd5841e2547357932aa1f8c93936 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 01:50:21 +0100 Subject: Issue #3080: Add PyImport_ImportFrozenModuleObject() find_frozen(), get_frozen_object(), is_frozen_package() and other functions related to frozen modules use Unicode strings instead of byte strings. --- Python/import.c | 98 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 37 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 9366be0589..09fc52cbda 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1429,7 +1429,7 @@ get_sourcefile(char *file) static PyObject *load_module(char *, FILE *, char *, int, PyObject *); static struct filedescr *find_module(char *, char *, PyObject *, char *, size_t, FILE **, PyObject **); -static struct _frozen * find_frozen(char *); +static struct _frozen * find_frozen(PyObject *); /* Load a package and return its module object WITH INCREMENTED REFERENCE COUNT */ @@ -1617,6 +1617,8 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, size_t saved_namelen; char *saved_buf = NULL; #endif + PyObject *fullname_obj; + if (p_loader != NULL) *p_loader = NULL; @@ -1662,9 +1664,16 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, Py_DECREF(meta_path); } - if (find_frozen(fullname) != NULL) { - strcpy(buf, fullname); - return &fd_frozen; + if (fullname != NULL) { + fullname_obj = PyUnicode_FromString(fullname); + if (fullname == NULL) + return NULL; + if (find_frozen(fullname_obj) != NULL) { + Py_DECREF(fullname_obj); + strcpy(buf, fullname); + return &fd_frozen; + } + Py_DECREF(fullname_obj); } if (path == NULL) { @@ -2226,37 +2235,37 @@ init_builtin(char *name) /* Frozen modules */ static struct _frozen * -find_frozen(char *name) +find_frozen(PyObject *name) { struct _frozen *p; - if (!name) + if (name == NULL) return NULL; for (p = PyImport_FrozenModules; ; p++) { if (p->name == NULL) return NULL; - if (strcmp(p->name, name) == 0) + if (PyUnicode_CompareWithASCIIString(name, p->name) == 0) break; } return p; } static PyObject * -get_frozen_object(char *name) +get_frozen_object(PyObject *name) { struct _frozen *p = find_frozen(name); int size; if (p == NULL) { PyErr_Format(PyExc_ImportError, - "No such frozen object named %.200s", + "No such frozen object named %R", name); return NULL; } if (p->code == NULL) { PyErr_Format(PyExc_ImportError, - "Excluded frozen object named %.200s", + "Excluded frozen object named %R", name); return NULL; } @@ -2267,14 +2276,14 @@ get_frozen_object(char *name) } static PyObject * -is_frozen_package(char *name) +is_frozen_package(PyObject *name) { struct _frozen *p = find_frozen(name); int size; if (p == NULL) { PyErr_Format(PyExc_ImportError, - "No such frozen object named %.200s", + "No such frozen object named %R", name); return NULL; } @@ -2294,19 +2303,20 @@ is_frozen_package(char *name) This function is also used from frozenmain.c */ int -PyImport_ImportFrozenModule(char *name) +PyImport_ImportFrozenModuleObject(PyObject *name) { - struct _frozen *p = find_frozen(name); - PyObject *co; - PyObject *m; + struct _frozen *p; + PyObject *co, *m, *path; int ispackage; int size; + p = find_frozen(name); + if (p == NULL) return 0; if (p->code == NULL) { PyErr_Format(PyExc_ImportError, - "Excluded frozen object named %.200s", + "Excluded frozen object named %R", name); return -1; } @@ -2315,40 +2325,41 @@ PyImport_ImportFrozenModule(char *name) if (ispackage) size = -size; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # frozen%s\n", + PySys_FormatStderr("import %U # frozen%s\n", name, ispackage ? " package" : ""); co = PyMarshal_ReadObjectFromString((char *)p->code, size); if (co == NULL) return -1; if (!PyCode_Check(co)) { PyErr_Format(PyExc_TypeError, - "frozen object %.200s is not a code object", + "frozen object %R is not a code object", name); goto err_return; } if (ispackage) { /* Set __path__ to the package name */ - PyObject *d, *s, *l; + PyObject *d, *l; int err; - m = PyImport_AddModule(name); + m = PyImport_AddModuleObject(name); if (m == NULL) goto err_return; d = PyModule_GetDict(m); - s = PyUnicode_InternFromString(name); - if (s == NULL) - goto err_return; l = PyList_New(1); if (l == NULL) { - Py_DECREF(s); goto err_return; } - PyList_SET_ITEM(l, 0, s); + Py_INCREF(name); + PyList_SET_ITEM(l, 0, name); err = PyDict_SetItemString(d, "__path__", l); Py_DECREF(l); if (err != 0) goto err_return; } - m = PyImport_ExecCodeModuleEx(name, co, ""); + path = PyUnicode_FromString(""); + if (path == NULL) + goto err_return; + m = PyImport_ExecCodeModuleObject(name, co, path, NULL); + Py_DECREF(path); if (m == NULL) goto err_return; Py_DECREF(co); @@ -2359,6 +2370,19 @@ err_return: return -1; } +int +PyImport_ImportFrozenModule(char *name) +{ + PyObject *nameobj; + int ret; + nameobj = PyUnicode_InternFromString(name); + if (nameobj == NULL) + return -1; + ret = PyImport_ImportFrozenModuleObject(nameobj); + Py_DECREF(nameobj); + return ret; +} + /* Import a module, either built-in, frozen, or external, and return its module object WITH INCREMENTED REFERENCE COUNT */ @@ -3282,19 +3306,19 @@ imp_init_builtin(PyObject *self, PyObject *args) static PyObject * imp_init_frozen(PyObject *self, PyObject *args) { - char *name; + PyObject *name; int ret; PyObject *m; - if (!PyArg_ParseTuple(args, "s:init_frozen", &name)) + if (!PyArg_ParseTuple(args, "U:init_frozen", &name)) return NULL; - ret = PyImport_ImportFrozenModule(name); + ret = PyImport_ImportFrozenModuleObject(name); if (ret < 0) return NULL; if (ret == 0) { Py_INCREF(Py_None); return Py_None; } - m = PyImport_AddModule(name); + m = PyImport_AddModuleObject(name); Py_XINCREF(m); return m; } @@ -3302,9 +3326,9 @@ imp_init_frozen(PyObject *self, PyObject *args) static PyObject * imp_get_frozen_object(PyObject *self, PyObject *args) { - char *name; + PyObject *name; - if (!PyArg_ParseTuple(args, "s:get_frozen_object", &name)) + if (!PyArg_ParseTuple(args, "U:get_frozen_object", &name)) return NULL; return get_frozen_object(name); } @@ -3312,9 +3336,9 @@ imp_get_frozen_object(PyObject *self, PyObject *args) static PyObject * imp_is_frozen_package(PyObject *self, PyObject *args) { - char *name; + PyObject *name; - if (!PyArg_ParseTuple(args, "s:is_frozen_package", &name)) + if (!PyArg_ParseTuple(args, "U:is_frozen_package", &name)) return NULL; return is_frozen_package(name); } @@ -3331,9 +3355,9 @@ imp_is_builtin(PyObject *self, PyObject *args) static PyObject * imp_is_frozen(PyObject *self, PyObject *args) { - char *name; + PyObject *name; struct _frozen *p; - if (!PyArg_ParseTuple(args, "s:is_frozen", &name)) + if (!PyArg_ParseTuple(args, "U:is_frozen", &name)) return NULL; p = find_frozen(name); return PyBool_FromLong((long) (p == NULL ? 0 : p->size)); -- cgit v1.2.1 From 17a3c1b5c7bb9b20e89c29ee9fcf6ee78a6cce82 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 7 Mar 2011 18:20:56 +0100 Subject: Issue #3080: Import builtins using Unicode strings - is_builtin(), init_builtin(), load_builtin() and other builtin related functions use Unicode strings, instead of byte strings - Rename _PyImport_FixupExtensionUnicode() to _PyImport_FixupExtensionObject() - Rename _PyImport_FindExtensionUnicode() to _PyImport_FindExtensionObject() --- Python/import.c | 112 +++++++++++++++++++++++++++++------------------------- Python/importdl.c | 24 +++++++++--- 2 files changed, 78 insertions(+), 58 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 09fc52cbda..597ef439c3 100644 --- a/Python/import.c +++ b/Python/import.c @@ -117,7 +117,7 @@ typedef unsigned short mode_t; static long pyc_magic = MAGIC; static const char *pyc_tag = TAG; -/* See _PyImport_FixupExtensionUnicode() below */ +/* See _PyImport_FixupExtensionObject() below */ static PyObject *extensions = NULL; /* This table is defined in config.c: */ @@ -563,10 +563,10 @@ PyImport_GetMagicTag(void) 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_FixupExtensionUnicode() + dictionary is stored by calling _PyImport_FixupExtensionObject() immediately after the module initialization function succeeds. A copy can be retrieved from there by calling - _PyImport_FindExtensionUnicode(). + _PyImport_FindExtensionObject(). Modules which do support multiple initialization set their m_size field to a non-negative number (indicating the size of the @@ -575,7 +575,8 @@ PyImport_GetMagicTag(void) */ int -_PyImport_FixupExtensionUnicode(PyObject *mod, char *name, PyObject *filename) +_PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, + PyObject *filename) { PyObject *modules, *dict; struct PyModuleDef *def; @@ -594,10 +595,10 @@ _PyImport_FixupExtensionUnicode(PyObject *mod, char *name, PyObject *filename) return -1; } modules = PyImport_GetModuleDict(); - if (PyDict_SetItemString(modules, name, mod) < 0) + if (PyDict_SetItem(modules, name, mod) < 0) return -1; if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItemString(modules, name); + PyDict_DelItem(modules, name); return -1; } if (def->m_size == -1) { @@ -623,17 +624,17 @@ int _PyImport_FixupBuiltin(PyObject *mod, char *name) { int res; - PyObject *filename; - filename = PyUnicode_FromString(name); - if (filename == NULL) + PyObject *nameobj; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) return -1; - res = _PyImport_FixupExtensionUnicode(mod, name, filename); - Py_DECREF(filename); + res = _PyImport_FixupExtensionObject(mod, nameobj, nameobj); + Py_DECREF(nameobj); return res; } PyObject * -_PyImport_FindExtensionUnicode(const char *name, PyObject *filename) +_PyImport_FindExtensionObject(PyObject *name, PyObject *filename) { PyObject *mod, *mdict; PyModuleDef* def; @@ -646,7 +647,7 @@ _PyImport_FindExtensionUnicode(const char *name, PyObject *filename) /* Module does not support repeated initialization */ if (def->m_base.m_copy == NULL) return NULL; - mod = PyImport_AddModule(name); + mod = PyImport_AddModuleObject(name); if (mod == NULL) return NULL; mdict = PyModule_GetDict(mod); @@ -661,16 +662,16 @@ _PyImport_FindExtensionUnicode(const char *name, PyObject *filename) mod = def->m_base.m_init(); if (mod == NULL) return NULL; - PyDict_SetItemString(PyImport_GetModuleDict(), name, mod); + PyDict_SetItem(PyImport_GetModuleDict(), name, mod); Py_DECREF(mod); } if (_PyState_AddModule(mod, def) < 0) { - PyDict_DelItemString(PyImport_GetModuleDict(), name); + PyDict_DelItem(PyImport_GetModuleDict(), name); Py_DECREF(mod); return NULL; } if (Py_VerboseFlag) - PySys_FormatStderr("import %s # previously loaded (%U)\n", + PySys_FormatStderr("import %U # previously loaded (%R)\n", name, filename); return mod; @@ -679,12 +680,12 @@ _PyImport_FindExtensionUnicode(const char *name, PyObject *filename) PyObject * _PyImport_FindBuiltin(const char *name) { - PyObject *res, *filename; - filename = PyUnicode_FromString(name); - if (filename == NULL) + PyObject *res, *nameobj; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) return NULL; - res = _PyImport_FindExtensionUnicode(name, filename); - Py_DECREF(filename); + res = _PyImport_FindExtensionObject(nameobj, nameobj); + Py_DECREF(nameobj); return res; } @@ -1491,11 +1492,12 @@ load_package(char *name, char *pathname) /* Helper to test for built-in module */ static int -is_builtin(char *name) +is_builtin(PyObject *name) { - int i; + int i, cmp; for (i = 0; PyImport_Inittab[i].name != NULL; i++) { - if (strcmp(name, PyImport_Inittab[i].name) == 0) { + cmp = PyUnicode_CompareWithASCIIString(name, PyImport_Inittab[i].name); + if (cmp == 0) { if (PyImport_Inittab[i].initfunc == NULL) return -1; else @@ -1617,7 +1619,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, size_t saved_namelen; char *saved_buf = NULL; #endif - PyObject *fullname_obj; + PyObject *fullname_obj, *nameobj; if (p_loader != NULL) *p_loader = NULL; @@ -1677,10 +1679,15 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, } if (path == NULL) { - if (is_builtin(name)) { + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + if (is_builtin(nameobj)) { + Py_DECREF(nameobj); strcpy(buf, name); return &fd_builtin; } + Py_DECREF(nameobj); #ifdef MS_COREDLL fp = _PyWin_FindRegisteredModule(name, &fdp, buf, buflen); if (fp != NULL) { @@ -2086,40 +2093,35 @@ find_init_module(char *buf) #endif /* HAVE_STAT */ -static int init_builtin(char *); /* Forward */ +static int init_builtin(PyObject *); /* Forward */ static PyObject* -load_builtin(char *name, char *pathname, int type) +load_builtin(PyObject *name, 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); + err = PyImport_ImportFrozenModuleObject(name); if (err < 0) return NULL; if (err == 0) { PyErr_Format(PyExc_ImportError, - "Purported %s module %.200s not found", - type == C_BUILTIN ? - "builtin" : "frozen", + "Purported %s module %R not found", + type == C_BUILTIN ? "builtin" : "frozen", name); return NULL; } modules = PyImport_GetModuleDict(); - m = PyDict_GetItemString(modules, name); + m = PyDict_GetItem(modules, name); if (m == NULL) { PyErr_Format( PyExc_ImportError, - "%s module %.200s not properly initialized", - type == C_BUILTIN ? - "builtin" : "frozen", + "%s module %R not properly initialized", + type == C_BUILTIN ? "builtin" : "frozen", name); return NULL; } @@ -2168,9 +2170,15 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) break; case C_BUILTIN: - case PY_FROZEN: - m = load_builtin(name, pathname, type); + case PY_FROZEN: { + PyObject *nameobj = PyUnicode_FromString(name); + if (nameobj != NULL) { + m = load_builtin(nameobj, type); + Py_DECREF(nameobj); + } else + m = NULL; break; + } case IMP_HOOK: { if (loader == NULL) { @@ -2199,28 +2207,28 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) an exception set if the initialization failed. */ static int -init_builtin(char *name) +init_builtin(PyObject *name) { struct _inittab *p; - if (_PyImport_FindBuiltin(name) != NULL) + if (_PyImport_FindExtensionObject(name, name) != NULL) return 1; for (p = PyImport_Inittab; p->name != NULL; p++) { PyObject *mod; - if (strcmp(name, p->name) == 0) { + if (PyUnicode_CompareWithASCIIString(name, p->name) == 0) { if (p->initfunc == NULL) { PyErr_Format(PyExc_ImportError, - "Cannot re-init internal module %.200s", + "Cannot re-init internal module %R", name); return -1; } if (Py_VerboseFlag) - PySys_WriteStderr("import %s # builtin\n", name); + PySys_FormatStderr("import %U # builtin\n", name); mod = (*p->initfunc)(); if (mod == 0) return -1; - if (_PyImport_FixupBuiltin(mod, name) < 0) + if (_PyImport_FixupExtensionObject(mod, name, name) < 0) return -1; /* FixupExtension has put the module into sys.modules, so we can release our own reference. */ @@ -3286,10 +3294,10 @@ imp_find_module(PyObject *self, PyObject *args) static PyObject * imp_init_builtin(PyObject *self, PyObject *args) { - char *name; + PyObject *name; int ret; PyObject *m; - if (!PyArg_ParseTuple(args, "s:init_builtin", &name)) + if (!PyArg_ParseTuple(args, "U:init_builtin", &name)) return NULL; ret = init_builtin(name); if (ret < 0) @@ -3298,7 +3306,7 @@ imp_init_builtin(PyObject *self, PyObject *args) Py_INCREF(Py_None); return Py_None; } - m = PyImport_AddModule(name); + m = PyImport_AddModuleObject(name); Py_XINCREF(m); return m; } @@ -3346,8 +3354,8 @@ imp_is_frozen_package(PyObject *self, PyObject *args) static PyObject * imp_is_builtin(PyObject *self, PyObject *args) { - char *name; - if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) + PyObject *name; + if (!PyArg_ParseTuple(args, "U:is_builtin", &name)) return NULL; return PyLong_FromLong(is_builtin(name)); } diff --git a/Python/importdl.c b/Python/importdl.c index 74ca8a7cca..f0e1f55d27 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -26,17 +26,23 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; - PyObject *result; + PyObject *nameobj, *result; path = PyUnicode_DecodeFSDefault(pathname); if (path == NULL) return NULL; - if ((m = _PyImport_FindExtensionUnicode(name, path)) != NULL) { + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + m = _PyImport_FindExtensionObject(nameobj, path); + if (m != NULL) { + Py_DECREF(nameobj); Py_INCREF(m); result = m; goto finally; } + Py_DECREF(nameobj); lastdot = strrchr(name, '.'); if (lastdot == NULL) { packagecontext = NULL; @@ -82,12 +88,18 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) else Py_INCREF(path); - if (_PyImport_FixupExtensionUnicode(m, name, path) < 0) + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + if (_PyImport_FixupExtensionObject(m, nameobj, path) < 0) { + Py_DECREF(nameobj); goto error; + } if (Py_VerboseFlag) - PySys_WriteStderr( - "import %s # dynamically loaded from %s\n", - name, pathname); + PySys_FormatStderr( + "import %U # dynamically loaded from %s\n", + nameobj, pathname); + Py_DECREF(nameobj); result = m; goto finally; -- cgit v1.2.1 From d08ceb04095b21f699c9221e7e5d7bb2b86a20ea Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 7 Mar 2011 18:28:15 +0100 Subject: Issue #3080: Use PyUnicode_InternFromString() for builtins _PyImport_FixupBuiltin() and _PyImport_FindBuiltin() use PyUnicode_InternFromString() instead of PyUnicode_FromString(). --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 597ef439c3..d43b881c2f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -625,7 +625,7 @@ _PyImport_FixupBuiltin(PyObject *mod, char *name) { int res; PyObject *nameobj; - nameobj = PyUnicode_FromString(name); + nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) return -1; res = _PyImport_FixupExtensionObject(mod, nameobj, nameobj); @@ -681,7 +681,7 @@ PyObject * _PyImport_FindBuiltin(const char *name) { PyObject *res, *nameobj; - nameobj = PyUnicode_FromString(name); + nameobj = PyUnicode_InternFromString(name); if (nameobj == NULL) return NULL; res = _PyImport_FindExtensionObject(nameobj, nameobj); -- cgit v1.2.1 From 4691aca1214aaa1b4433a667d875415f9a27c38e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 8 Mar 2011 23:49:04 +0100 Subject: Issue #3080: _PyWin_FindRegisteredModule() returns the path as Unicode * Document the function * Use RegQueryValueW() instead of RegQueryValueA() * Use _Py_fopen() instead of fopen() * Allocate registry key on the heap, not on the stack, and handle memory allocation failure * Handle Python exception in find_module() --- Python/import.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index d43b881c2f..8fab810eec 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1591,8 +1591,8 @@ PyImport_GetImporter(PyObject *path) { pathname and an open file. Return NULL if the module is not found. */ #ifdef MS_COREDLL -extern FILE *_PyWin_FindRegisteredModule(const char *, struct filedescr **, - char *, Py_ssize_t); +extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, + PyObject **p_path); #endif static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); @@ -1679,6 +1679,9 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, } if (path == NULL) { +#ifdef MS_COREDLL + PyObject *filename, *filename_bytes; +#endif nameobj = PyUnicode_FromString(name); if (nameobj == NULL) return NULL; @@ -1687,14 +1690,24 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, strcpy(buf, name); return &fd_builtin; } - Py_DECREF(nameobj); #ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(name, &fdp, buf, buflen); + fp = _PyWin_FindRegisteredModule(nameobj, &fdp, &filename); if (fp != NULL) { + Py_DECREF(nameobj); + filename_bytes = PyUnicode_EncodeFSDefault(filename); + Py_DECREF(filename); + if (filename_bytes == NULL) + return NULL; + strncpy(buf, PyBytes_AS_STRING(filename_bytes), buflen); + buf[buflen-1] = '\0'; + Py_DECREF(filename_bytes); *p_fp = fp; return fdp; } + else if (PyErr_Occurred()) + return NULL; #endif + Py_DECREF(nameobj); path = PySys_GetObject("path"); } -- cgit v1.2.1 From 7c1cd6d18d5ac37ec86183e7fabcf35ff11e3d21 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 15:54:07 -0400 Subject: Issue #3080: _PyImport_LoadDynamicModule() uses Unicode for name and path Document also that dynamic module names are ASCII only --- Python/import.c | 54 +++++++++++++++++++++++------------------- Python/importdl.c | 70 +++++++++++++++++++++++-------------------------------- Python/importdl.h | 2 +- 3 files changed, 60 insertions(+), 66 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 8fab810eec..4e5cb2ddbf 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2173,9 +2173,21 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) break; #ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: - m = _PyImport_LoadDynamicModule(name, pathname, fp); + case C_EXTENSION: { + 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 = _PyImport_LoadDynamicModule(nameobj, pathobj, fp); + Py_DECREF(nameobj); + Py_DECREF(pathobj); break; + } #endif case PKG_DIRECTORY: @@ -2185,11 +2197,10 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) case C_BUILTIN: case PY_FROZEN: { PyObject *nameobj = PyUnicode_FromString(name); - if (nameobj != NULL) { - m = load_builtin(nameobj, type); - Py_DECREF(nameobj); - } else - m = NULL; + if (nameobj == NULL) + return NULL; + m = load_builtin(nameobj, type); + Py_DECREF(nameobj); break; } @@ -3443,28 +3454,23 @@ imp_load_compiled(PyObject *self, PyObject *args) 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, "sO&|O:load_dynamic", - &name, PyUnicode_FSConverter, &pathbytes, &fob)) + PyObject *name, *pathname, *fob = NULL, *mod; + FILE *fp; + + if (!PyArg_ParseTuple(args, "UO&|O:load_dynamic", + &name, PyUnicode_FSDecoder, &pathname, &fob)) return NULL; - pathname = PyBytes_AS_STRING(pathbytes); - if (fob) { - fp = get_file(pathname, fob, "r"); - if (fp == NULL) { - Py_DECREF(pathbytes); + if (fob != NULL) { + fp = get_file(NULL, fob, "r"); + if (fp == NULL) return NULL; - } } - m = _PyImport_LoadDynamicModule(name, pathname, fp); - Py_DECREF(pathbytes); + else + fp = NULL; + mod = _PyImport_LoadDynamicModule(name, pathname, fp); if (fp) fclose(fp); - return m; + return mod; } #endif /* HAVE_DYNAMIC_LOADING */ diff --git a/Python/importdl.c b/Python/importdl.c index f0e1f55d27..629f3e294e 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -15,67 +15,68 @@ extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp); - +/* name should be ASCII only because the C language doesn't accept non-ASCII + identifiers, and dynamic modules are written in C. */ PyObject * -_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) +_PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) { PyObject *m; - PyObject *path; - char *lastdot, *shortname, *packagecontext, *oldcontext; + PyObject *pathbytes; + char *namestr, *lastdot, *shortname, *packagecontext, *oldcontext; dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; - PyObject *nameobj, *result; - path = PyUnicode_DecodeFSDefault(pathname); - if (path == NULL) + namestr = _PyUnicode_AsString(name); + if (namestr == NULL) return NULL; - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - return NULL; - m = _PyImport_FindExtensionObject(nameobj, path); + m = _PyImport_FindExtensionObject(name, path); if (m != NULL) { - Py_DECREF(nameobj); Py_INCREF(m); - result = m; - goto finally; + return m; } - Py_DECREF(nameobj); - lastdot = strrchr(name, '.'); + + lastdot = strrchr(namestr, '.'); if (lastdot == NULL) { packagecontext = NULL; - shortname = name; + shortname = namestr; } else { - packagecontext = name; + packagecontext = namestr; shortname = lastdot+1; } - p0 = _PyImport_GetDynLoadFunc(shortname, pathname, fp); + pathbytes = PyUnicode_EncodeFSDefault(path); + if (pathbytes == NULL) + return NULL; + p0 = _PyImport_GetDynLoadFunc(shortname, + PyBytes_AS_STRING(pathbytes), fp); + Py_DECREF(pathbytes); p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) - goto error; + return NULL; if (p == NULL) { PyErr_Format(PyExc_ImportError, - "dynamic module does not define init function (PyInit_%.200s)", + "dynamic module does not define init function" + " (PyInit_%s)", shortname); - goto error; + return NULL; } oldcontext = _Py_PackageContext; _Py_PackageContext = packagecontext; m = (*p)(); _Py_PackageContext = oldcontext; if (m == NULL) - goto error; + return NULL; if (PyErr_Occurred()) { Py_DECREF(m); PyErr_Format(PyExc_SystemError, "initialization of %s raised unreported exception", shortname); - goto error; + return NULL; } /* Remember pointer to module init function. */ @@ -88,26 +89,13 @@ _PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp) else Py_INCREF(path); - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) + if (_PyImport_FixupExtensionObject(m, name, path) < 0) return NULL; - if (_PyImport_FixupExtensionObject(m, nameobj, path) < 0) { - Py_DECREF(nameobj); - goto error; - } if (Py_VerboseFlag) PySys_FormatStderr( - "import %U # dynamically loaded from %s\n", - nameobj, pathname); - Py_DECREF(nameobj); - result = m; - goto finally; - -error: - result = NULL; -finally: - Py_DECREF(path); - return result; + "import %U # dynamically loaded from %R\n", + name, path); + return m; } #endif /* HAVE_DYNAMIC_LOADING */ diff --git a/Python/importdl.h b/Python/importdl.h index b4d21be6f0..e51e551ff9 100644 --- a/Python/importdl.h +++ b/Python/importdl.h @@ -28,7 +28,7 @@ struct filedescr { extern struct filedescr * _PyImport_Filetab; extern const struct filedescr _PyImport_DynLoadFiletab[]; -extern PyObject *_PyImport_LoadDynamicModule(char *name, char *pathname, +extern PyObject *_PyImport_LoadDynamicModule(PyObject *name, PyObject *pathname, FILE *); /* Max length of module suffix searched for -- accommodates "module.slb" */ -- cgit v1.2.1 From ab8eed250aee0dfe2e0e8cc1472113d5d2b4b9c7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 12 Mar 2011 08:45:02 -0500 Subject: Issue #3080: find_module() initialize buf and *p_fp Document also the find_module() function --- Python/import.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 4e5cb2ddbf..e58d6a04be 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1443,7 +1443,7 @@ load_package(char *name, char *pathname) PyObject *path = NULL; int err; char buf[MAXPATHLEN+1]; - FILE *fp = NULL; + FILE *fp; struct filedescr *fdp; m = PyImport_AddModule(name); @@ -1464,7 +1464,6 @@ load_package(char *name, char *pathname) err = PyDict_SetItemString(d, "__path__", path); if (err != 0) goto error; - buf[0] = '\0'; fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { @@ -1599,6 +1598,31 @@ static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); static int find_init_module(char *); /* Forward */ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; +/* Find a module: + + - try find_module() of each sys.meta_path hook + - try find_frozen() + - try is_builtin() + - try _PyWin_FindRegisteredModule() (Windows only) + - otherwise, call find_module_path_list() with search_path_list (if not + NULL) or sys.path + + Return: + + - &fd_builtin (C_BUILTIN) if it is a builtin + - &fd_frozen (PY_FROZEN) if it is frozen + - &fd_package (PKG_DIRECTORY) and write the filename into *buf + if it is a package + - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a + importer loader was found + - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or + PY_CODERESOURCE: see _PyImport_Filetab), write the filename into + *buf and the pointer to the open file into *p_fp + - NULL on error + + By default, write an empty string into *buf, and *p_fp and *p_loader (if + set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ + static struct filedescr * find_module(char *fullname, char *subname, PyObject *path, char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) @@ -1621,6 +1645,8 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, #endif PyObject *fullname_obj, *nameobj; + *buf = '\0'; + *p_fp = NULL; if (p_loader != NULL) *p_loader = NULL; @@ -2962,10 +2988,10 @@ import_submodule(PyObject *mod, char *subname, char *fullname) Py_INCREF(m); } else { - PyObject *path, *loader = NULL; + PyObject *path, *loader; char buf[MAXPATHLEN+1]; struct filedescr *fdp; - FILE *fp = NULL; + FILE *fp; if (mod == Py_None) path = NULL; @@ -2978,7 +3004,6 @@ import_submodule(PyObject *mod, char *subname, char *fullname) } } - buf[0] = '\0'; fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1, &fp, &loader); Py_XDECREF(path); @@ -3012,11 +3037,11 @@ PyImport_ReloadModule(PyObject *m) PyInterpreterState *interp = PyThreadState_Get()->interp; PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - PyObject *path = NULL, *loader = NULL, *existing_m = NULL; + PyObject *path = NULL, *loader, *existing_m = NULL; char *name, *subname; char buf[MAXPATHLEN+1]; struct filedescr *fdp; - FILE *fp = NULL; + FILE *fp; PyObject *newm; if (modules_reloading == NULL) { @@ -3074,7 +3099,6 @@ PyImport_ReloadModule(PyObject *m) if (path == NULL) PyErr_Clear(); } - buf[0] = '\0'; fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader); Py_XDECREF(path); @@ -3252,7 +3276,7 @@ call_find_module(char *name, PyObject *path) PyObject *pathobj; struct filedescr *fdp; char pathname[MAXPATHLEN+1]; - FILE *fp = NULL; + FILE *fp; int fd = -1; char *found_encoding = NULL; char *encoding = NULL; -- cgit v1.2.1 From 8d647fdca120414a1901c3b1414b405ad7f415f4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 12 Mar 2011 09:26:54 -0500 Subject: Issue #3080: Remove useless name buffer from find_module() Rename subname argument to name, and mark it as constant. --- Python/import.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e58d6a04be..37cd4b81f2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1428,7 +1428,7 @@ get_sourcefile(char *file) /* Forward */ static PyObject *load_module(char *, FILE *, char *, int, PyObject *); -static struct filedescr *find_module(char *, char *, PyObject *, +static struct filedescr *find_module(char *, const char *, PyObject *, char *, size_t, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); @@ -1594,7 +1594,7 @@ extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, PyObject **p_path); #endif -static int case_ok(char *, Py_ssize_t, Py_ssize_t, char *); +static int case_ok(char *, Py_ssize_t, Py_ssize_t, const char *); static int find_init_module(char *); /* Forward */ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; @@ -1624,7 +1624,7 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ static struct filedescr * -find_module(char *fullname, char *subname, PyObject *path, char *buf, +find_module(char *fullname, const char *name, PyObject *path, char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; @@ -1637,7 +1637,6 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, static struct filedescr fd_frozen = {"", "", PY_FROZEN}; static struct filedescr fd_builtin = {"", "", C_BUILTIN}; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - char name[MAXPATHLEN+1]; #if defined(PYOS_OS2) size_t saved_len; size_t saved_namelen; @@ -1650,12 +1649,11 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, if (p_loader != NULL) *p_loader = NULL; - if (strlen(subname) > MAXPATHLEN) { + if (strlen(name) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, "module name is too long"); return NULL; } - strcpy(name, subname); /* sys.meta_path import hook */ if (p_loader != NULL) { @@ -1867,7 +1865,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, * dynamically loaded module we're going to try, * truncate the name before trying */ - if (strlen(subname) > 8) { + if (strlen(name) > 8) { /* is this an attempt to load a C extension? */ const struct filedescr *scan; scan = _PyImport_DynLoadFiletab; @@ -1880,7 +1878,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, if (scan->suffix != NULL) { /* yes, so truncate the name */ namelen = 8; - len -= strlen(subname) - namelen; + len -= strlen(name) - namelen; buf[len] = '\0'; } } @@ -1972,7 +1970,7 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, #endif static int -case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, char *name) +case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) { /* Pick a platform-specific implementation; the sequence of #if's here should * match the sequence just above. -- cgit v1.2.1 From f44ffd60a466519364cc45d367f3505f1ecbe090 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 01:34:43 +0100 Subject: Issue #3080: Create find_module_path_list() subfunction --- Python/import.c | 310 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 164 insertions(+), 146 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 37cd4b81f2..565f1336cb 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1598,168 +1598,30 @@ static int case_ok(char *, Py_ssize_t, Py_ssize_t, const char *); static int find_init_module(char *); /* Forward */ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; -/* Find a module: - - - try find_module() of each sys.meta_path hook - - try find_frozen() - - try is_builtin() - - try _PyWin_FindRegisteredModule() (Windows only) - - otherwise, call find_module_path_list() with search_path_list (if not - NULL) or sys.path - - Return: - - - &fd_builtin (C_BUILTIN) if it is a builtin - - &fd_frozen (PY_FROZEN) if it is frozen - - &fd_package (PKG_DIRECTORY) and write the filename into *buf - if it is a package - - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a - importer loader was found - - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or - PY_CODERESOURCE: see _PyImport_Filetab), write the filename into - *buf and the pointer to the open file into *p_fp - - NULL on error - - By default, write an empty string into *buf, and *p_fp and *p_loader (if - set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ - -static struct filedescr * -find_module(char *fullname, const char *name, PyObject *path, char *buf, - size_t buflen, FILE **p_fp, PyObject **p_loader) +static struct filedescr* +find_module_path_list(char *fullname, const char *name, + PyObject *search_path_list, PyObject *path_hooks, + PyObject *path_importer_cache, + char *buf, size_t buflen, + FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; size_t len, namelen; struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; - PyObject *path_hooks, *path_importer_cache; struct stat statbuf; - static struct filedescr fd_frozen = {"", "", PY_FROZEN}; - static struct filedescr fd_builtin = {"", "", C_BUILTIN}; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; #if defined(PYOS_OS2) size_t saved_len; size_t saved_namelen; char *saved_buf = NULL; #endif - PyObject *fullname_obj, *nameobj; - *buf = '\0'; - *p_fp = NULL; - if (p_loader != NULL) - *p_loader = NULL; - - if (strlen(name) > MAXPATHLEN) { - PyErr_SetString(PyExc_OverflowError, - "module name is too long"); - return NULL; - } - - /* sys.meta_path import hook */ - if (p_loader != NULL) { - PyObject *meta_path; - - meta_path = PySys_GetObject("meta_path"); - if (meta_path == NULL || !PyList_Check(meta_path)) { - PyErr_SetString(PyExc_ImportError, - "sys.meta_path must be a list of " - "import hooks"); - return NULL; - } - Py_INCREF(meta_path); /* zap guard */ - npath = PyList_Size(meta_path); - for (i = 0; i < npath; i++) { - PyObject *loader; - PyObject *hook = PyList_GetItem(meta_path, i); - loader = PyObject_CallMethod(hook, "find_module", - "sO", fullname, - path != NULL ? - path : Py_None); - if (loader == NULL) { - Py_DECREF(meta_path); - return NULL; /* true error */ - } - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - Py_DECREF(meta_path); - return &importhookdescr; - } - Py_DECREF(loader); - } - Py_DECREF(meta_path); - } - - if (fullname != NULL) { - fullname_obj = PyUnicode_FromString(fullname); - if (fullname == NULL) - return NULL; - if (find_frozen(fullname_obj) != NULL) { - Py_DECREF(fullname_obj); - strcpy(buf, fullname); - return &fd_frozen; - } - Py_DECREF(fullname_obj); - } - - if (path == NULL) { -#ifdef MS_COREDLL - PyObject *filename, *filename_bytes; -#endif - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - return NULL; - if (is_builtin(nameobj)) { - Py_DECREF(nameobj); - strcpy(buf, name); - return &fd_builtin; - } -#ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(nameobj, &fdp, &filename); - if (fp != NULL) { - Py_DECREF(nameobj); - filename_bytes = PyUnicode_EncodeFSDefault(filename); - Py_DECREF(filename); - if (filename_bytes == NULL) - return NULL; - strncpy(buf, PyBytes_AS_STRING(filename_bytes), buflen); - buf[buflen-1] = '\0'; - Py_DECREF(filename_bytes); - *p_fp = fp; - return fdp; - } - else if (PyErr_Occurred()) - return NULL; -#endif - Py_DECREF(nameobj); - path = PySys_GetObject("path"); - } - - if (path == NULL || !PyList_Check(path)) { - PyErr_SetString(PyExc_ImportError, - "sys.path must be a list of directory names"); - return NULL; - } - - path_hooks = PySys_GetObject("path_hooks"); - if (path_hooks == NULL || !PyList_Check(path_hooks)) { - PyErr_SetString(PyExc_ImportError, - "sys.path_hooks must be a list of " - "import hooks"); - return NULL; - } - path_importer_cache = PySys_GetObject("path_importer_cache"); - if (path_importer_cache == NULL || - !PyDict_Check(path_importer_cache)) { - PyErr_SetString(PyExc_ImportError, - "sys.path_importer_cache must be a dict"); - return NULL; - } - - npath = PyList_Size(path); + npath = PyList_Size(search_path_list); namelen = strlen(name); for (i = 0; i < npath; i++) { - PyObject *v = PyList_GetItem(path, i); + PyObject *v = PyList_GetItem(search_path_list, i); PyObject *origv = v; const char *base; Py_ssize_t size; @@ -1925,6 +1787,162 @@ find_module(char *fullname, const char *name, PyObject *path, char *buf, return fdp; } +/* Find a module: + + - try find_module() of each sys.meta_path hook + - try find_frozen() + - try is_builtin() + - try _PyWin_FindRegisteredModule() (Windows only) + - otherwise, call find_module_path_list() with search_path_list (if not + NULL) or sys.path + + Return: + + - &fd_builtin (C_BUILTIN) if it is a builtin + - &fd_frozen (PY_FROZEN) if it is frozen + - &fd_package (PKG_DIRECTORY) and write the filename into *buf + if it is a package + - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a + importer loader was found + - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or + PY_CODERESOURCE: see _PyImport_Filetab), write the filename into + *buf and the pointer to the open file into *p_fp + - NULL on error + + By default, write an empty string into *buf, and *p_fp and *p_loader (if + set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ + +static struct filedescr * +find_module(char *fullname, const char *name, PyObject *search_path_list, + char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) +{ + Py_ssize_t i, npath; + static struct filedescr fd_frozen = {"", "", PY_FROZEN}; + static struct filedescr fd_builtin = {"", "", C_BUILTIN}; + PyObject *path_hooks, *path_importer_cache; + PyObject *fullname_obj, *nameobj; + + *buf = '\0'; + *p_fp = NULL; + if (p_loader != NULL) + *p_loader = NULL; + + if (strlen(name) > MAXPATHLEN) { + PyErr_SetString(PyExc_OverflowError, + "module name is too long"); + return NULL; + } + + /* sys.meta_path import hook */ + if (p_loader != NULL) { + PyObject *meta_path; + + meta_path = PySys_GetObject("meta_path"); + if (meta_path == NULL || !PyList_Check(meta_path)) { + PyErr_SetString(PyExc_ImportError, + "sys.meta_path must be a list of " + "import hooks"); + return NULL; + } + Py_INCREF(meta_path); /* zap guard */ + npath = PyList_Size(meta_path); + for (i = 0; i < npath; i++) { + PyObject *loader; + PyObject *hook = PyList_GetItem(meta_path, i); + loader = PyObject_CallMethod(hook, "find_module", + "sO", fullname, + search_path_list != NULL ? + search_path_list : Py_None); + if (loader == NULL) { + Py_DECREF(meta_path); + return NULL; /* true error */ + } + if (loader != Py_None) { + /* a loader was found */ + *p_loader = loader; + Py_DECREF(meta_path); + return &importhookdescr; + } + Py_DECREF(loader); + } + Py_DECREF(meta_path); + } + + if (fullname != NULL) { + fullname_obj = PyUnicode_FromString(fullname); + if (fullname == NULL) + return NULL; + if (find_frozen(fullname_obj) != NULL) { + Py_DECREF(fullname_obj); + strcpy(buf, fullname); + return &fd_frozen; + } + Py_DECREF(fullname_obj); + } + + if (search_path_list == NULL) { +#ifdef MS_COREDLL + FILE *fp; + struct filedescr *fdp; + PyObject *filename, *filename_bytes; +#endif + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + if (is_builtin(nameobj)) { + Py_DECREF(nameobj); + strcpy(buf, name); + return &fd_builtin; + } +#ifdef MS_COREDLL + fp = _PyWin_FindRegisteredModule(nameobj, &fdp, &filename); + if (fp != NULL) { + Py_DECREF(nameobj); + filename_bytes = PyUnicode_EncodeFSDefault(filename); + Py_DECREF(filename); + if (filename_bytes == NULL) + return NULL; + strncpy(buf, PyBytes_AS_STRING(filename_bytes), buflen); + buf[buflen-1] = '\0'; + Py_DECREF(filename_bytes); + *p_fp = fp; + return fdp; + } + else if (PyErr_Occurred()) + return NULL; +#endif + Py_DECREF(nameobj); + search_path_list = PySys_GetObject("path"); + } + + if (search_path_list == NULL || !PyList_Check(search_path_list)) { + PyErr_SetString(PyExc_ImportError, + "sys.path must be a list of directory names"); + return NULL; + } + + path_hooks = PySys_GetObject("path_hooks"); + if (path_hooks == NULL || !PyList_Check(path_hooks)) { + PyErr_SetString(PyExc_ImportError, + "sys.path_hooks must be a list of " + "import hooks"); + return NULL; + } + path_importer_cache = PySys_GetObject("path_importer_cache"); + if (path_importer_cache == NULL || + !PyDict_Check(path_importer_cache)) { + PyErr_SetString(PyExc_ImportError, + "sys.path_importer_cache must be a dict"); + return NULL; + } + + return find_module_path_list(fullname, name, + search_path_list, path_hooks, + path_importer_cache, + buf, buflen, + p_fp, p_loader); +} + /* 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 -- cgit v1.2.1 From 2d77d7eabcf50177446677639435d797b85722e7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 12 Mar 2011 16:02:28 -0500 Subject: Issue #3080: Create find_module_path() subfunction --- Python/import.c | 228 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 139 insertions(+), 89 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 565f1336cb..59b284654e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1598,6 +1598,129 @@ static int case_ok(char *, Py_ssize_t, Py_ssize_t, const char *); static int find_init_module(char *); /* Forward */ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; +/* Get the path of a module: get its importer and call importer.find_module() + hook, or check if the module if a package (if path/__init__.py exists). + + -1: error: a Python error occurred + 0: ignore: an error occurred because of invalid data, but the error is not + important enough to be reported. + 1: get path: module not found, but *buf contains its path + 2: found: *p_fd is the file descriptor (IMP_HOOK or PKG_DIRECTORY) + and *buf is the path */ + +static int +find_module_path(char *fullname, const char *name, PyObject *path, + PyObject *path_hooks, PyObject *path_importer_cache, + char *buf, size_t buflen, + PyObject **p_loader, struct filedescr **p_fd) +{ + PyObject *path_bytes; + const char *base; + Py_ssize_t len; + size_t namelen; + struct stat statbuf; + static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; + + if (PyUnicode_Check(path)) { + path_bytes = PyUnicode_EncodeFSDefault(path); + if (path_bytes == NULL) + return -1; + } + else if (PyBytes_Check(path)) { + Py_INCREF(path); + path_bytes = path; + } + else + return 0; + + namelen = strlen(name); + base = PyBytes_AS_STRING(path_bytes); + len = PyBytes_GET_SIZE(path_bytes); + if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { + Py_DECREF(path_bytes); + return 0; /* Too long */ + } + strcpy(buf, base); + Py_DECREF(path_bytes); + + if (strlen(buf) != len) { + return 0; /* path_bytes contains '\0' */ + } + + /* sys.path_hooks import hook */ + if (p_loader != NULL) { + PyObject *importer; + + importer = get_path_importer(path_importer_cache, + path_hooks, path); + if (importer == NULL) { + return -1; + } + /* Note: importer is a borrowed reference */ + if (importer != Py_None) { + PyObject *loader; + loader = PyObject_CallMethod(importer, + "find_module", + "s", fullname); + if (loader == NULL) + return -1; /* error */ + if (loader != Py_None) { + /* a loader was found */ + *p_loader = loader; + *p_fd = &importhookdescr; + return 2; + } + Py_DECREF(loader); + return 0; + } + } + /* no hook was found, use builtin import */ + + if (len > 0 && buf[len-1] != SEP +#ifdef ALTSEP + && buf[len-1] != ALTSEP +#endif + ) + buf[len++] = SEP; + strcpy(buf+len, name); + len += namelen; + + /* Check for package import (buf holds a directory name, + and there's an __init__ module in that directory */ +#ifdef HAVE_STAT + if (stat(buf, &statbuf) == 0 && /* it exists */ + S_ISDIR(statbuf.st_mode) && /* it's a directory */ + case_ok(buf, len, namelen, name)) { /* case matches */ + if (find_init_module(buf)) { /* and has __init__.py */ + *p_fd = &fd_package; + return 2; + } + else { + int err; + PyObject *unicode = PyUnicode_DecodeFSDefault(buf); + if (unicode == NULL) + return -1; + err = PyErr_WarnFormat(PyExc_ImportWarning, 1, + "Not importing directory '%U': missing __init__.py", + unicode); + Py_DECREF(unicode); + if (err) + return -1; + } + } +#endif + return 1; +} + +/* Find a module in search_path_list. For each path, try + find_module_filename() or try each _PyImport_Filetab suffix. + + If the module is found, return a file descriptor, write the path in + *p_filename, write the pointer to the file object into *p_fp, and (if + p_loader is not NULL) the loader into *p_loader. + + Otherwise, raise an exception and return NULL. */ + static struct filedescr* find_module_path_list(char *fullname, const char *name, PyObject *search_path_list, PyObject *path_hooks, @@ -1610,8 +1733,6 @@ find_module_path_list(char *fullname, const char *name, struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; - struct stat statbuf; - static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; #if defined(PYOS_OS2) size_t saved_len; size_t saved_namelen; @@ -1621,96 +1742,25 @@ find_module_path_list(char *fullname, const char *name, npath = PyList_Size(search_path_list); namelen = strlen(name); for (i = 0; i < npath; i++) { - PyObject *v = PyList_GetItem(search_path_list, i); - PyObject *origv = v; - const char *base; - Py_ssize_t size; - if (!v) - return NULL; - if (PyUnicode_Check(v)) { - v = PyUnicode_EncodeFSDefault(v); - if (v == NULL) - return NULL; - } - else if (!PyBytes_Check(v)) - continue; - else - Py_INCREF(v); - - base = PyBytes_AS_STRING(v); - size = PyBytes_GET_SIZE(v); - len = size; - if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { - Py_DECREF(v); - continue; /* Too long */ - } - strcpy(buf, base); - Py_DECREF(v); + PyObject *path; + int ok; - if (strlen(buf) != len) { - continue; /* v contains '\0' */ - } - - /* sys.path_hooks import hook */ - if (p_loader != NULL) { - PyObject *importer; - - importer = get_path_importer(path_importer_cache, - path_hooks, origv); - if (importer == NULL) { - return NULL; - } - /* Note: importer is a borrowed reference */ - if (importer != Py_None) { - PyObject *loader; - loader = PyObject_CallMethod(importer, - "find_module", - "s", fullname); - if (loader == NULL) - return NULL; /* error */ - if (loader != Py_None) { - /* a loader was found */ - *p_loader = loader; - return &importhookdescr; - } - Py_DECREF(loader); - continue; - } - } - /* no hook was found, use builtin import */ + path = PyList_GetItem(search_path_list, i); + if (path == NULL) + return NULL; - if (len > 0 && buf[len-1] != SEP -#ifdef ALTSEP - && buf[len-1] != ALTSEP -#endif - ) - buf[len++] = SEP; - strcpy(buf+len, name); - len += namelen; + ok = find_module_path(fullname, name, path, + path_hooks, path_importer_cache, + buf, buflen, + p_loader, &fdp); + if (ok < 0) + return NULL; + if (ok == 0) + continue; + if (ok == 2) + return fdp; - /* Check for package import (buf holds a directory name, - and there's an __init__ module in that directory */ -#ifdef HAVE_STAT - if (stat(buf, &statbuf) == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode) && /* it's a directory */ - case_ok(buf, len, namelen, name)) { /* case matches */ - if (find_init_module(buf)) { /* and has __init__.py */ - return &fd_package; - } - else { - 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 + len = strlen(buf); #if defined(PYOS_OS2) /* take a snapshot of the module spec for restoration * after the 8 character DLL hackery -- cgit v1.2.1 From 8509b2931d82b09524d8922b5ffd1871f5ff6311 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 13:33:46 -0400 Subject: Issue #3080: get_sourcefile(), make_source_pathname(), load_package() Use Unicode for module name and path in get_sourcefile(), make_source_pathname() and load_package() functions. --- Python/import.c | 219 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 131 insertions(+), 88 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 59b284654e..f6cde957a8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -113,6 +113,8 @@ typedef unsigned short mode_t; #define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-32" #define CACHEDIR "__pycache__" +static const Py_UNICODE CACHEDIR_UNICODE[] = { + '_', '_', 'p', 'y', 'c', 'a', 'c', 'h', 'e', '_', '_', '\0'}; /* Current magic word and string tag as globals. */ static long pyc_magic = MAGIC; static const char *pyc_tag = TAG; @@ -741,8 +743,8 @@ remove_module(PyObject *name) "sys.modules failed"); } -static PyObject * get_sourcefile(char *file); -static char *make_source_pathname(char *pathname, char *buf); +static PyObject * get_sourcefile(PyObject *filename); +static PyObject *make_source_pathname(PyObject *pathname); static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug); @@ -807,7 +809,6 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, { PyObject *modules = PyImport_GetModuleDict(); PyObject *m, *d, *v; - PyObject *pathbytes; m = PyImport_AddModuleObject(name); if (m == NULL) @@ -822,12 +823,7 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, } /* Remember the filename as the __file__ attribute */ if (pathname != NULL) { - pathbytes = PyUnicode_EncodeFSDefault(pathname); - if (pathbytes != NULL) { - v = get_sourcefile(PyBytes_AS_STRING(pathbytes)); - Py_DECREF(pathbytes); - } else - v = NULL; + v = get_sourcefile(pathname); if (v == NULL) PyErr_Clear(); } @@ -892,6 +888,27 @@ rightmost_sep(char *s) } +/* Like strrchr(string, '/') but searches for the rightmost of either SEP + or ALTSEP, if the latter is defined. +*/ +static Py_UNICODE* +rightmost_sep_unicode(Py_UNICODE *s) +{ + Py_UNICODE *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. @@ -1005,42 +1022,50 @@ make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) 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. */ + the resulting path will always be shorter. -static char * -make_source_pathname(char *pathname, char *buf) + (...)/__pycache__/foo..pyc -> (...)/foo.py */ + +static PyObject* +make_source_pathname(PyObject *pathobj) { - /* __pycache__/foo..pyc -> foo.py */ + Py_UNICODE buf[MAXPATHLEN]; + Py_UNICODE *pathname; + Py_UNICODE *left, *right, *dot0, *dot1, sep; size_t i, j; - char *left, *right, *dot0, *dot1, sep; + + if (PyUnicode_GET_SIZE(pathobj) > MAXPATHLEN) + return NULL; + pathname = PyUnicode_AS_UNICODE(pathobj); /* 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) + right = rightmost_sep_unicode(pathname); + if (right == NULL) return NULL; sep = *right; *right = '\0'; - left = rightmost_sep(pathname); + left = rightmost_sep_unicode(pathname); *right = sep; if (left == NULL) left = pathname; else left++; - if (right-left != strlen(CACHEDIR) || - strncmp(left, CACHEDIR, right-left) != 0) + if (right-left != Py_UNICODE_strlen(CACHEDIR_UNICODE) || + Py_UNICODE_strncmp(left, CACHEDIR_UNICODE, 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) + if ((dot0 = Py_UNICODE_strchr(right + 1, '.')) == NULL) return NULL; - if ((dot1 = strchr(dot0 + 1, '.')) == NULL) + if ((dot1 = Py_UNICODE_strchr(dot0 + 1, '.')) == NULL) return NULL; /* Too many dots? */ - if (strchr(dot1 + 1, '.') != NULL) + if (Py_UNICODE_strchr(dot1 + 1, '.') != NULL) return NULL; /* This is a PEP 3147 path. Start by copying everything from the @@ -1048,10 +1073,11 @@ make_source_pathname(char *pathname, char *buf) 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; + Py_UNICODE_strncpy(buf, pathname, (i=left-pathname)); + Py_UNICODE_strncpy(buf+i, right+1, (j=dot0-right)); + buf[i+j] = 'p'; + buf[i+j+1] = 'y'; + return PyUnicode_FromUnicode(buf, i+j+2); } /* Given a pathname for a Python source file, its time of last @@ -1390,40 +1416,47 @@ 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(char *file) +get_sourcefile(PyObject *filename) { - char py[MAXPATHLEN + 1]; Py_ssize_t len; - PyObject *u; + Py_UNICODE *fileuni; + PyObject *py; struct stat statbuf; - if (!file || !*file) { + len = PyUnicode_GET_SIZE(filename); + if (len == 0) Py_RETURN_NONE; - } - len = strlen(file); - /* match '*.py?' */ - if (len > MAXPATHLEN || PyOS_strnicmp(&file[len-4], ".py", 3) != 0) { - return PyUnicode_DecodeFSDefault(file); - } + /* don't match *.pyc or *.pyo? */ + fileuni = PyUnicode_AS_UNICODE(filename); + if (len < 5 + || fileuni[len-4] != '.' + || (fileuni[len-3] != 'p' && fileuni[len-3] != 'P') + || (fileuni[len-2] != 'y' && fileuni[len-2] != 'Y')) + goto unchanged; /* 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'; + py = make_source_pathname(filename); + if (py == NULL) { + PyErr_Clear(); + py = PyUnicode_FromUnicode(fileuni, len - 1); } + if (py == NULL) + goto error; - if (stat(py, &statbuf) == 0 && - S_ISREG(statbuf.st_mode)) { - u = PyUnicode_DecodeFSDefault(py); - } - else { - u = PyUnicode_DecodeFSDefault(file); - } - return u; + if (_Py_stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) + return py; + Py_DECREF(py); + goto unchanged; + +error: + PyErr_Clear(); +unchanged: + Py_INCREF(filename); + return filename; } /* Forward */ @@ -1436,54 +1469,56 @@ static struct _frozen * find_frozen(PyObject *); REFERENCE COUNT */ static PyObject * -load_package(char *name, char *pathname) +load_package(PyObject *name, PyObject *pathname) { PyObject *m, *d; - PyObject *file = NULL; - PyObject *path = NULL; + PyObject *file = NULL, *path_list = NULL; int err; char buf[MAXPATHLEN+1]; - FILE *fp; + FILE *fp = NULL; struct filedescr *fdp; + char *namestr; - m = PyImport_AddModule(name); + m = PyImport_AddModuleObject(name); if (m == NULL) return NULL; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # directory %s\n", + PySys_FormatStderr("import %U # directory %U\n", name, pathname); - d = PyModule_GetDict(m); file = get_sourcefile(pathname); if (file == NULL) - goto error; - path = Py_BuildValue("[O]", file); - if (path == NULL) - goto error; + return NULL; + path_list = Py_BuildValue("[O]", file); + if (path_list == NULL) { + Py_DECREF(file); + return NULL; + } + d = PyModule_GetDict(m); err = PyDict_SetItemString(d, "__file__", file); + Py_DECREF(file); if (err == 0) - err = PyDict_SetItemString(d, "__path__", path); - if (err != 0) + err = PyDict_SetItemString(d, "__path__", path_list); + if (err != 0) { + Py_DECREF(path_list); + return NULL; + } + namestr = _PyUnicode_AsString(name); + if (namestr == NULL) goto error; - fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL); + fdp = find_module(namestr, "__init__", path_list, buf, sizeof(buf), &fp, NULL); + Py_DECREF(path_list); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { PyErr_Clear(); Py_INCREF(m); + return m; } else - m = NULL; - goto cleanup; + return NULL; } - m = load_module(name, fp, buf, fdp->type, NULL); + m = load_module(namestr, fp, buf, fdp->type, NULL); if (fp != NULL) fclose(fp); - goto cleanup; - - error: - m = NULL; - cleanup: - Py_XDECREF(path); - Py_XDECREF(file); return m; } @@ -2282,9 +2317,21 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) } #endif - case PKG_DIRECTORY: - m = load_package(name, pathname); + case PKG_DIRECTORY: { + 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_package(nameobj, pathobj); + Py_DECREF(nameobj); + Py_DECREF(pathobj); break; + } case C_BUILTIN: case PY_FROZEN: { @@ -3637,13 +3684,12 @@ imp_load_module(PyObject *self, PyObject *args) static PyObject * imp_load_package(PyObject *self, PyObject *args) { - char *name; - PyObject *pathname; + PyObject *name, *pathname; PyObject * ret; - if (!PyArg_ParseTuple(args, "sO&:load_package", - &name, PyUnicode_FSConverter, &pathname)) + if (!PyArg_ParseTuple(args, "UO&:load_package", + &name, PyUnicode_FSDecoder, &pathname)) return NULL; - ret = load_package(name, PyBytes_AS_STRING(pathname)); + ret = load_package(name, pathname); Py_DECREF(pathname); return ret; } @@ -3716,25 +3762,22 @@ 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]; + PyObject *pathname, *source; if (!PyArg_ParseTupleAndKeywords( args, kws, "O&", kwlist, - PyUnicode_FSConverter, &pathname_obj)) + PyUnicode_FSDecoder, &pathname)) 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", + source = make_source_pathname(pathname); + if (source == NULL) { + PyErr_Format(PyExc_ValueError, "Not a PEP 3147 pyc path: %R", pathname); - Py_DECREF(pathname_obj); + Py_DECREF(pathname); return NULL; } - Py_DECREF(pathname_obj); - return PyUnicode_FromString(buf); + Py_DECREF(pathname); + return source; } PyDoc_STRVAR(doc_source_from_cache, -- cgit v1.2.1 From 26e6d2c66ccad73bad2edeb441f54141164d0bc1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 00:41:24 +0100 Subject: 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 --- Python/import.c | 352 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 201 insertions(+), 151 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index f6cde957a8..0efffe9149 100644 --- a/Python/import.c +++ b/Python/import.c @@ -107,8 +107,8 @@ typedef unsigned short mode_t; /* 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. + TAG and PYC_TAG_UNICODE 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" @@ -118,6 +118,8 @@ static const Py_UNICODE CACHEDIR_UNICODE[] = { /* Current magic word and string tag as globals. */ static long pyc_magic = MAGIC; 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 */ static PyObject *extensions = NULL; @@ -745,8 +747,7 @@ remove_module(PyObject *name) static PyObject * get_sourcefile(PyObject *filename); static PyObject *make_source_pathname(PyObject *pathname); -static char *make_compiled_pathname(char *pathname, char *buf, size_t buflen, - int debug); +static PyObject* make_compiled_pathname(Py_UNICODE *pathname, int debug); /* Execute a code object in a module and return the module object * 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 or ALTSEP, if the latter is defined. */ static Py_UNICODE* -rightmost_sep_unicode(Py_UNICODE *s) +rightmost_sep(Py_UNICODE *s) { Py_UNICODE *found, c; 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 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. */ + Doesn't set an exception. + + foo.py -> __pycache__/foo..pyc */ -static char * -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..pyc */ - size_t len = strlen(pathname); + Py_UNICODE buf[MAXPATHLEN]; + size_t buflen = (size_t)MAXPATHLEN; + size_t len = Py_UNICODE_strlen(pathname); size_t i, save; - char *pos; + Py_UNICODE *pos; int sep = SEP; /* 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 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; /* 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) { + pos = rightmost_sep(pathname); + if (pos == NULL) { i = 0; } else { sep = *pos; i = pos - pathname + 1; - strncpy(buf, pathname, i); + Py_UNICODE_strncpy(buf, pathname, i); } save = i; buf[i++] = '\0'; /* Add __pycache__/ */ - strcat(buf, CACHEDIR); - i += strlen(CACHEDIR) - 1; + Py_UNICODE_strcat(buf, CACHEDIR_UNICODE); + i += Py_UNICODE_strlen(CACHEDIR_UNICODE) - 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) + Py_UNICODE_strcat(buf, pathname + save); + pos = Py_UNICODE_strrchr(buf, '.'); + if (pos != NULL) *++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 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 @@ -1010,11 +995,15 @@ make_compiled_pathname(char *pathname, char *buf, size_t buflen, int debug) #if 0 printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); #endif - if (strlen(buf) + 5 > buflen) + len = Py_UNICODE_strlen(buf); + if (len + 5 > buflen) return NULL; - strcat(buf, debug ? ".pyc" : ".pyo"); - assert(strlen(buf) < buflen); - return buf; + buf[len] = '.'; len++; + buf[len] = 'p'; len++; + 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 path. It's possible for there to be only one slash. */ - right = rightmost_sep_unicode(pathname); + right = rightmost_sep(pathname); if (right == NULL) return NULL; sep = *right; *right = '\0'; - left = rightmost_sep_unicode(pathname); + left = rightmost_sep(pathname); *right = sep; if (left == NULL) left = pathname; @@ -1088,31 +1077,31 @@ make_source_pathname(PyObject *pathobj) Doesn't set an exception. */ static FILE * -check_compiled_module(char *pathname, time_t mtime, char *cpathname) +check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname) { FILE *fp; long magic; long pyc_mtime; - fp = fopen(cpathname, "rb"); + fp = _Py_fopen(cpathname, "rb"); if (fp == NULL) return NULL; magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad magic\n", cpathname); + PySys_FormatStderr("# %R has bad magic\n", cpathname); fclose(fp); return NULL; } pyc_mtime = PyMarshal_ReadLongFromFile(fp); if (pyc_mtime != mtime) { if (Py_VerboseFlag) - PySys_WriteStderr("# %s has bad mtime\n", cpathname); + PySys_FormatStderr("# %R has bad mtime\n", cpathname); fclose(fp); return NULL; } if (Py_VerboseFlag) - PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); + PySys_FormatStderr("# %R matches %R\n", cpathname, pathname); 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 */ static PyCodeObject * -read_compiled_module(char *cpathname, FILE *fp) +read_compiled_module(PyObject *cpathname, FILE *fp) { PyObject *co; @@ -1129,7 +1118,7 @@ read_compiled_module(char *cpathname, FILE *fp) return NULL; if (!PyCode_Check(co)) { PyErr_Format(PyExc_ImportError, - "Non-code object in %.200s", cpathname); + "Non-code object in %R", cpathname); Py_DECREF(co); return NULL; } @@ -1141,7 +1130,7 @@ read_compiled_module(char *cpathname, FILE *fp) module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * -load_compiled_module(char *name, char *cpathname, FILE *fp) +load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp) { long magic; PyCodeObject *co; @@ -1150,7 +1139,7 @@ load_compiled_module(char *name, char *cpathname, FILE *fp) magic = PyMarshal_ReadLongFromFile(fp); if (magic != pyc_magic) { PyErr_Format(PyExc_ImportError, - "Bad magic number in %.200s", cpathname); + "Bad magic number in %R", cpathname); return NULL; } (void) PyMarshal_ReadLongFromFile(fp); @@ -1158,10 +1147,10 @@ load_compiled_module(char *name, char *cpathname, FILE *fp) if (co == NULL) return NULL; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); - m = PyImport_ExecCodeModuleWithPathnames( - name, (PyObject *)co, cpathname, cpathname); + PySys_FormatStderr("import %U # precompiled from %R\n", + name, cpathname); + m = PyImport_ExecCodeModuleObject(name, (PyObject *)co, + cpathname, cpathname); Py_DECREF(co); 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 */ 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; PyCompilerFlags flags; - PyArena *arena = PyArena_New(); - if (arena == NULL) + 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, pathname, NULL, + mod = PyParser_ASTFromFile(fp, PyBytes_AS_STRING(pathbytes), NULL, Py_file_input, 0, 0, &flags, NULL, arena); - if (mod) { - co = PyAST_Compile(mod, pathname, 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; } - /* Helper to open a bytecode file for writing in exclusive mode */ static FILE * @@ -1231,10 +1230,10 @@ open_exclusive(char *filename, mode_t mode) remove the file. */ static void -write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) +write_compiled_module(PyCodeObject *co, PyObject *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; @@ -1243,39 +1242,64 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) mode_t dirmode = (srcstat->st_mode | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR | S_IWGRP | S_IWOTH); + PyObject *dirbytes; #endif - int saved; + PyObject *cpathbytes, *dirname; + Py_UNICODE *dirsep; + int res, ok; /* Ensure that the __pycache__ directory exists. */ - dirpath = rightmost_sep(cpathname); - if (dirpath == NULL) { + dirsep = rightmost_sep(PyUnicode_AS_UNICODE(cpathname)); + if (dirsep == NULL) { if (Py_VerboseFlag) - PySys_WriteStderr( - "# no %s path found %s\n", - CACHEDIR, cpathname); + PySys_FormatStderr("# no %s path found %R\n", CACHEDIR, cpathname); + return; + } + dirname = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(cpathname), + dirsep - PyUnicode_AS_UNICODE(cpathname)); + if (dirname == NULL) { + PyErr_Clear(); return; } - saved = *dirpath; - *dirpath = '\0'; #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 - if (mkdir(cpathname, dirmode) < 0 && errno != EEXIST) { + 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 - *dirpath = saved; + if (!ok) { if (Py_VerboseFlag) - PySys_WriteStderr( - "# cannot create cache dir %s\n", cpathname); + PySys_FormatStderr("# cannot create cache dir %R\n", dirname); + Py_DECREF(dirname); + return; + } + Py_DECREF(dirname); + + cpathbytes = PyUnicode_EncodeFSDefault(cpathname); + if (cpathbytes == NULL) { + PyErr_Clear(); return; } - *dirpath = saved; - fp = open_exclusive(cpathname, mode); + fp = open_exclusive(PyBytes_AS_STRING(cpathbytes), mode); if (fp == NULL) { if (Py_VerboseFlag) - PySys_WriteStderr( - "# can't create %s\n", cpathname); + PySys_FormatStderr( + "# can't create %R\n", cpathname); + Py_DECREF(cpathbytes); return; } 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); if (fflush(fp) != 0 || ferror(fp)) { if (Py_VerboseFlag) - PySys_WriteStderr("# can't write %s\n", cpathname); + PySys_FormatStderr("# can't write %R\n", cpathname); /* Don't keep partial file */ 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; } + Py_DECREF(cpathbytes); /* Now write the true mtime */ fseek(fp, 4L, 0); assert(mtime < LONG_MAX); @@ -1297,7 +1327,7 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat) fflush(fp); fclose(fp); if (Py_VerboseFlag) - PySys_WriteStderr("# wrote %s\n", cpathname); + PySys_FormatStderr("# wrote %R\n", cpathname); } static void @@ -1324,26 +1354,18 @@ update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname) } } -static int -update_compiled_module(PyCodeObject *co, char *pathname) +static void +update_compiled_module(PyCodeObject *co, PyObject *newname) { - PyObject *oldname, *newname; + PyObject *oldname; - newname = PyUnicode_DecodeFSDefault(pathname); - if (newname == NULL) - return -1; - - if (!PyUnicode_Compare(co->co_filename, newname)) { - Py_DECREF(newname); - return 0; - } + if (PyUnicode_Compare(co->co_filename, newname) == 0) + return; oldname = co->co_filename; Py_INCREF(oldname); update_code_filenames(co, oldname, newname); Py_DECREF(oldname); - Py_DECREF(newname); - return 1; } /* 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. */ static PyObject * -load_source_module(char *name, char *pathname, FILE *fp) +load_source_module(PyObject *name, PyObject *pathname, FILE *fp) { struct stat st; FILE *fpc; - char buf[MAXPATHLEN+1]; - char *cpathname; + PyObject *cpathname = NULL, *cpathbytes = NULL; PyCodeObject *co; - PyObject *m; + PyObject *m = NULL; if (fstat(fileno(fp), &st) != 0) { PyErr_Format(PyExc_RuntimeError, - "unable to get file status from '%s'", + "unable to get file status from %R", pathname); - return NULL; + goto error; } #if SIZEOF_TIME_T > 4 /* 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) { PyErr_SetString(PyExc_OverflowError, "modification time overflows a 4 byte field"); - return NULL; + goto error; } #endif cpathname = make_compiled_pathname( - pathname, buf, (size_t)MAXPATHLEN + 1, !Py_OptimizeFlag); - if (cpathname != NULL && - (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) { + PyUnicode_AS_UNICODE(pathname), + !Py_OptimizeFlag); + + if (cpathname != NULL) + fpc = check_compiled_module(pathname, st.st_mtime, cpathname); + else + fpc = NULL; + + if (fpc) { co = read_compiled_module(cpathname, fpc); fclose(fpc); if (co == NULL) - return NULL; - if (update_compiled_module(co, pathname) < 0) - return NULL; + goto error; + update_compiled_module(co, pathname); if (Py_VerboseFlag) - PySys_WriteStderr("import %s # precompiled from %s\n", - name, cpathname); - pathname = cpathname; + 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) - return NULL; + goto error; if (Py_VerboseFlag) - PySys_WriteStderr("import %s # from %s\n", + PySys_FormatStderr("import %U # from %R\n", name, pathname); - if (cpathname) { + 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); } - m = PyImport_ExecCodeModuleWithPathnames( - name, (PyObject *)co, pathname, cpathname); Py_DECREF(co); +error: + Py_XDECREF(cpathbytes); + Py_XDECREF(cpathname); return m; } @@ -2291,13 +2321,37 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) switch (type) { - case PY_SOURCE: - m = load_source_module(name, pathname, fp); + case PY_SOURCE: { + 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; + } - case PY_COMPILED: - m = load_compiled_module(name, pathname, fp); + case PY_COMPILED: { + 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; + } #ifdef HAVE_DYNAMIC_LOADING case C_EXTENSION: { @@ -3533,13 +3587,13 @@ imp_is_frozen(PyObject *self, PyObject *args) } static FILE * -get_file(char *pathname, PyObject *fob, char *mode) +get_file(PyObject *pathname, PyObject *fob, char *mode) { FILE *fp; if (mode[0] == 'U') mode = "r" PY_STDIOTEXTMODE; if (fob == NULL) { - fp = fopen(pathname, mode); + fp = _Py_fopen(pathname, mode); } else { int fd = PyObject_AsFileDescriptor(fob); @@ -3565,22 +3619,21 @@ error: static PyObject * imp_load_compiled(PyObject *self, PyObject *args) { - char *name; - PyObject *pathname; + PyObject *name, *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "sO&|O:load_compiled", + if (!PyArg_ParseTuple(args, "UO&|O:load_compiled", &name, - PyUnicode_FSConverter, &pathname, + PyUnicode_FSDecoder, &pathname, &fob)) return NULL; - fp = get_file(PyBytes_AS_STRING(pathname), fob, "rb"); + fp = get_file(pathname, fob, "rb"); if (fp == NULL) { Py_DECREF(pathname); return NULL; } - m = load_compiled_module(name, PyBytes_AS_STRING(pathname), fp); + m = load_compiled_module(name, pathname, fp); fclose(fp); Py_DECREF(pathname); return m; @@ -3615,22 +3668,21 @@ imp_load_dynamic(PyObject *self, PyObject *args) static PyObject * imp_load_source(PyObject *self, PyObject *args) { - char *name; - PyObject *pathname; + PyObject *name, *pathname; PyObject *fob = NULL; PyObject *m; FILE *fp; - if (!PyArg_ParseTuple(args, "sO&|O:load_source", + if (!PyArg_ParseTuple(args, "UO&|O:load_source", &name, - PyUnicode_FSConverter, &pathname, + PyUnicode_FSDecoder, &pathname, &fob)) return NULL; - fp = get_file(PyBytes_AS_STRING(pathname), fob, "r"); + fp = get_file(pathname, fob, "r"); if (fp == NULL) { Py_DECREF(pathname); return NULL; } - m = load_source_module(name, PyBytes_AS_STRING(pathname), fp); + m = load_source_module(name, pathname, fp); Py_DECREF(pathname); fclose(fp); return m; @@ -3719,33 +3771,31 @@ 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 *pathname, *cpathname; PyObject *debug_override = NULL; int debug = !Py_OptimizeFlag; if (!PyArg_ParseTupleAndKeywords( args, kws, "O&|O", kwlist, - PyUnicode_FSConverter, &pathbytes, &debug_override)) + PyUnicode_FSDecoder, &pathname, &debug_override)) return NULL; if (debug_override != NULL && (debug = PyObject_IsTrue(debug_override)) < 0) { - Py_DECREF(pathbytes); + Py_DECREF(pathname); return NULL; } cpathname = make_compiled_pathname( - PyBytes_AS_STRING(pathbytes), - buf, MAXPATHLEN+1, debug); - Py_DECREF(pathbytes); + PyUnicode_AS_UNICODE(pathname), + debug); + Py_DECREF(pathname); if (cpathname == NULL) { PyErr_Format(PyExc_SystemError, "path buffer too short"); return NULL; } - return PyUnicode_DecodeFSDefault(buf); + return cpathname; } PyDoc_STRVAR(doc_cache_from_source, -- cgit v1.2.1 From 1bd9d3e0561cad30f87017b5ee00be6f7c92ced8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Mar 2011 21:46:30 -0400 Subject: Issue #3080: load_module() expects name and path as Unicode --- Python/import.c | 136 +++++++++++++++++++++++--------------------------------- 1 file changed, 55 insertions(+), 81 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 0efffe9149..00a9eccaf8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1490,7 +1490,7 @@ unchanged: } /* Forward */ -static PyObject *load_module(char *, FILE *, char *, int, PyObject *); +static PyObject *load_module(PyObject *, FILE *, PyObject *, int, PyObject *); static struct filedescr *find_module(char *, const char *, PyObject *, char *, size_t, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); @@ -1501,7 +1501,7 @@ static struct _frozen * find_frozen(PyObject *); static PyObject * load_package(PyObject *name, PyObject *pathname) { - PyObject *m, *d; + PyObject *m, *d, *bufobj; PyObject *file = NULL, *path_list = NULL; int err; char buf[MAXPATHLEN+1]; @@ -1546,7 +1546,13 @@ load_package(PyObject *name, PyObject *pathname) else return NULL; } - m = load_module(namestr, fp, buf, fdp->type, NULL); + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + m = load_module(name, fp, bufobj, fdp->type, NULL); + Py_DECREF(bufobj); + } + else + m = NULL; if (fp != NULL) fclose(fp); return m; @@ -2303,7 +2309,7 @@ load_builtin(PyObject *name, int type) its module object WITH INCREMENTED REFERENCE COUNT */ static PyObject * -load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) +load_module(PyObject *name, FILE *fp, PyObject *pathname, int type, PyObject *loader) { PyObject *m; @@ -2313,7 +2319,7 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) case PY_COMPILED: if (fp == NULL) { PyErr_Format(PyExc_ValueError, - "file object required for import (type code %d)", + "file object required for import (type code %d)", type); return NULL; } @@ -2321,81 +2327,28 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) switch (type) { - case PY_SOURCE: { - 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); + case PY_SOURCE: + m = load_source_module(name, pathname, fp); break; - } - case PY_COMPILED: { - 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); + case PY_COMPILED: + m = load_compiled_module(name, pathname, fp); break; - } #ifdef HAVE_DYNAMIC_LOADING - case C_EXTENSION: { - 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 = _PyImport_LoadDynamicModule(nameobj, pathobj, fp); - Py_DECREF(nameobj); - Py_DECREF(pathobj); + case C_EXTENSION: + m = _PyImport_LoadDynamicModule(name, pathname, fp); break; - } #endif - case PKG_DIRECTORY: { - 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_package(nameobj, pathobj); - Py_DECREF(nameobj); - Py_DECREF(pathobj); + case PKG_DIRECTORY: + m = load_package(name, pathname); break; - } case C_BUILTIN: - case PY_FROZEN: { - PyObject *nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - return NULL; - m = load_builtin(nameobj, type); - Py_DECREF(nameobj); + case PY_FROZEN: + m = load_builtin(name, type); break; - } case IMP_HOOK: { if (loader == NULL) { @@ -2403,13 +2356,13 @@ load_module(char *name, FILE *fp, char *pathname, int type, PyObject *loader) "import hook without loader"); return NULL; } - m = PyObject_CallMethod(loader, "load_module", "s", name); + m = PyObject_CallMethod(loader, "load_module", "O", name); break; } default: PyErr_Format(PyExc_ImportError, - "Don't know how to import %.200s (type code %d)", + "Don't know how to import %U (type code %d)", name, type); m = NULL; @@ -3144,7 +3097,7 @@ static PyObject * import_submodule(PyObject *mod, char *subname, char *fullname) { PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL; + PyObject *m = NULL, *fullnameobj, *bufobj; /* Require: if mod == None: subname == fullname @@ -3181,7 +3134,19 @@ import_submodule(PyObject *mod, char *subname, char *fullname) Py_INCREF(Py_None); return Py_None; } - m = load_module(fullname, fp, buf, fdp->type, loader); + fullnameobj = PyUnicode_FromString(fullname); + if (fullnameobj != NULL) { + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + m = load_module(fullnameobj, fp, bufobj, fdp->type, loader); + Py_DECREF(bufobj); + } + else + m = NULL; + Py_DECREF(fullnameobj); + } + else + m = NULL; Py_XDECREF(loader); if (fp) fclose(fp); @@ -3209,7 +3174,7 @@ PyImport_ReloadModule(PyObject *m) char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp; - PyObject *newm; + PyObject *newm, *nameobj, *bufobj; if (modules_reloading == NULL) { Py_FatalError("PyImport_ReloadModule: " @@ -3275,7 +3240,19 @@ PyImport_ReloadModule(PyObject *m) return NULL; } - newm = load_module(name, fp, buf, fdp->type, loader); + nameobj = PyUnicode_FromString(name); + if (nameobj != NULL) { + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + newm = load_module(nameobj, fp, bufobj, fdp->type, loader); + Py_DECREF(bufobj); + } + else + newm = NULL; + Py_DECREF(nameobj); + } + else + newm = NULL; Py_XDECREF(loader); if (fp) @@ -3691,18 +3668,15 @@ imp_load_source(PyObject *self, PyObject *args) static PyObject * imp_load_module(PyObject *self, PyObject *args) { - char *name; - PyObject *fob; - PyObject *pathname; - PyObject * ret; + PyObject *name, *fob, *pathname, *ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "sOO&(ssi):load_module", + if (!PyArg_ParseTuple(args, "UOO&(ssi):load_module", &name, &fob, - PyUnicode_FSConverter, &pathname, + PyUnicode_FSDecoder, &pathname, &suffix, &mode, &type)) return NULL; if (*mode) { @@ -3726,7 +3700,7 @@ imp_load_module(PyObject *self, PyObject *args) return NULL; } } - ret = load_module(name, fp, PyBytes_AS_STRING(pathname), type, NULL); + ret = load_module(name, fp, pathname, type, NULL); Py_DECREF(pathname); if (fp) fclose(fp); -- cgit v1.2.1 From d5668295d2303564770b7dbdfbb02e7d007292bc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Mar 2011 21:57:27 -0400 Subject: Issue #3080: PyImport_ImportModuleNoBlock() uses Unicode --- Python/import.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 00a9eccaf8..08237aff95 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2591,8 +2591,7 @@ PyImport_ImportModule(const char *name) PyObject * PyImport_ImportModuleNoBlock(const char *name) { - PyObject *result; - PyObject *modules; + PyObject *nameobj, *modules, *result; long me; /* Try to get the module from sys.modules[name] */ @@ -2600,14 +2599,16 @@ PyImport_ImportModuleNoBlock(const char *name) if (modules == NULL) return NULL; - result = PyDict_GetItemString(modules, name); + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + result = PyDict_GetItem(modules, nameobj); if (result != NULL) { + Py_DECREF(nameobj); Py_INCREF(result); return result; } - else { - PyErr_Clear(); - } + PyErr_Clear(); #ifdef WITH_THREAD /* check the import lock * me might be -1 but I ignore the error here, the lock function @@ -2615,18 +2616,20 @@ PyImport_ImportModuleNoBlock(const char *name) me = PyThread_get_thread_ident(); if (import_lock_thread == -1 || import_lock_thread == me) { /* no thread or me is holding the lock */ - return PyImport_ImportModule(name); + result = PyImport_Import(nameobj); } else { PyErr_Format(PyExc_ImportError, - "Failed to import %.200s because the import lock" + "Failed to import %U because the import lock" "is held by another thread.", - name); - return NULL; + nameobj); + result = NULL; } #else - return PyImport_ImportModule(name); + result = PyImport_Import(nameobj); #endif + Py_DECREF(nameobj); + return result; } /* Forward declarations for helper routines */ -- cgit v1.2.1 From 93d6b25bf514369f9325ae1dd062a7ba9f1c1097 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 15 Mar 2011 09:33:57 +0100 Subject: Issue #3080: Use Unicode for the "The Magnum Opus of dotted-name import" Use Unicode for module name and paths in the following functions: * PyImport_ImportModuleLevel() * add_submodule() * ensure_from_list() * get_parent() * import_module_level() * import_submodule() * load_next() * mark_miss() --- Python/import.c | 381 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 222 insertions(+), 159 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 08237aff95..95faeee5d8 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2633,28 +2633,37 @@ PyImport_ImportModuleNoBlock(const char *name) } /* Forward declarations for helper routines */ -static PyObject *get_parent(PyObject *globals, char *buf, - Py_ssize_t *p_buflen, int level); +static PyObject *get_parent(PyObject *globals, + PyObject **p_name, + int level); static PyObject *load_next(PyObject *mod, PyObject *altmod, - char **p_name, char *buf, Py_ssize_t *p_buflen); -static int mark_miss(char *name); + PyObject *inputname, PyObject **p_outputname, + Py_UNICODE *buf, Py_ssize_t *p_buflen, + Py_ssize_t bufsize); +static int mark_miss(PyObject *name); static int ensure_fromlist(PyObject *mod, PyObject *fromlist, - char *buf, Py_ssize_t buflen, int recursive); -static PyObject * import_submodule(PyObject *mod, char *name, char *fullname); + PyObject *buf, int recursive); +static PyObject * import_submodule(PyObject *mod, PyObject *name, + PyObject *fullname); /* The Magnum Opus of dotted-name import :-) */ static PyObject * -import_module_level(char *name, PyObject *globals, PyObject *locals, +import_module_level(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { - char buf[MAXPATHLEN+1]; - Py_ssize_t buflen = 0; - PyObject *parent, *head, *next, *tail; + Py_UNICODE buf[MAXPATHLEN+1]; + Py_ssize_t buflen; + Py_ssize_t bufsize = MAXPATHLEN+1; + PyObject *parent, *head, *next, *tail, *inputname, *outputname; + PyObject *parent_name, *ensure_name; + const Py_UNICODE *nameunicode; - if (strchr(name, '/') != NULL -#ifdef MS_WINDOWS - || strchr(name, '\\') != NULL + nameunicode = PyUnicode_AS_UNICODE(name); + + if (Py_UNICODE_strchr(nameunicode, SEP) != NULL +#ifdef ALTSEP + || Py_UNICODE_strchr(nameunicode, ALTSEP) != NULL #endif ) { PyErr_SetString(PyExc_ImportError, @@ -2662,25 +2671,45 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, return NULL; } - parent = get_parent(globals, buf, &buflen, level); + parent = get_parent(globals, &parent_name, level); if (parent == NULL) return NULL; - head = load_next(parent, level < 0 ? Py_None : parent, &name, buf, - &buflen); + buflen = PyUnicode_GET_SIZE(parent_name); + if (buflen+1 > bufsize) { + Py_DECREF(parent_name); + PyErr_SetString(PyExc_ValueError, + "Module name too long"); + return NULL; + } + Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(parent_name)); + Py_DECREF(parent_name); + + head = load_next(parent, level < 0 ? Py_None : parent, name, &outputname, + buf, &buflen, bufsize); if (head == NULL) return NULL; tail = head; Py_INCREF(tail); - while (name) { - next = load_next(tail, tail, &name, buf, &buflen); - Py_DECREF(tail); - if (next == NULL) { - Py_DECREF(head); - return NULL; + + if (outputname != NULL) { + while (1) { + inputname = outputname; + next = load_next(tail, tail, inputname, &outputname, + buf, &buflen, bufsize); + Py_DECREF(tail); + Py_DECREF(inputname); + if (next == NULL) { + Py_DECREF(head); + return NULL; + } + tail = next; + + if (outputname == NULL) { + break; + } } - tail = next; } if (tail == Py_None) { /* If tail is Py_None, both get_parent and load_next found @@ -2688,8 +2717,7 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, doctored faulty bytecode */ Py_DECREF(tail); Py_DECREF(head); - PyErr_SetString(PyExc_ValueError, - "Empty module name"); + PyErr_SetString(PyExc_ValueError, "Empty module name"); return NULL; } @@ -2704,21 +2732,33 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, } Py_DECREF(head); - if (!ensure_fromlist(tail, fromlist, buf, buflen, 0)) { + + ensure_name = PyUnicode_FromUnicode(buf, Py_UNICODE_strlen(buf)); + if (ensure_name == NULL) { + Py_DECREF(tail); + return NULL; + } + if (!ensure_fromlist(tail, fromlist, ensure_name, 0)) { Py_DECREF(tail); + Py_DECREF(ensure_name); return NULL; } + Py_DECREF(ensure_name); return tail; } PyObject * PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) + PyObject *fromlist, int level) { - PyObject *result; + PyObject *nameobj, *result; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; _PyImport_AcquireLock(); - result = import_module_level(name, globals, locals, fromlist, level); + result = import_module_level(nameobj, globals, locals, fromlist, level); + Py_DECREF(nameobj); if (_PyImport_ReleaseLock() < 0) { Py_XDECREF(result); PyErr_SetString(PyExc_RuntimeError, @@ -2733,15 +2773,20 @@ PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, sys.modules entry for foo.bar. If globals is from a package's __init__.py, the package's entry in sys.modules is returned, as a borrowed reference. - The *name* of the returned package is returned in buf, with the length of - the name in *p_buflen. + The name of the returned package is returned in *p_name. If globals doesn't come from a package or a module in a package, or a corresponding entry is not found in sys.modules, Py_None is returned. */ static PyObject * -get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) +get_parent(PyObject *globals, + PyObject **p_name, + int level) { + Py_UNICODE name[MAXPATHLEN+1]; + const Py_ssize_t bufsize = MAXPATHLEN+1; + PyObject *nameobj; + static PyObject *namestr = NULL; static PyObject *pathstr = NULL; static PyObject *pkgstr = NULL; @@ -2749,7 +2794,7 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) int orig_level = level; if (globals == NULL || !PyDict_Check(globals) || !level) - return Py_None; + goto return_none; if (namestr == NULL) { namestr = PyUnicode_InternFromString("__name__"); @@ -2767,55 +2812,46 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) return NULL; } - *buf = '\0'; - *p_buflen = 0; pkgname = PyDict_GetItem(globals, pkgstr); if ((pkgname != NULL) && (pkgname != Py_None)) { /* __package__ is set, so use it */ - char *pkgname_str; - Py_ssize_t len; - if (!PyUnicode_Check(pkgname)) { PyErr_SetString(PyExc_ValueError, "__package__ set to non-string"); return NULL; } - pkgname_str = _PyUnicode_AsStringAndSize(pkgname, &len); - if (len == 0) { + if (PyUnicode_GET_SIZE(pkgname) == 0) { if (level > 0) { PyErr_SetString(PyExc_ValueError, "Attempted relative import in non-package"); return NULL; } - return Py_None; + goto return_none; } - if (len > MAXPATHLEN) { + if (PyUnicode_GET_SIZE(pkgname)+1 > bufsize) { PyErr_SetString(PyExc_ValueError, "Package name too long"); return NULL; } - strcpy(buf, pkgname_str); + Py_UNICODE_strcpy(name, PyUnicode_AS_UNICODE(pkgname)); } else { /* __package__ not set, so figure it out and set it */ modname = PyDict_GetItem(globals, namestr); if (modname == NULL || !PyUnicode_Check(modname)) - return Py_None; + goto return_none; modpath = PyDict_GetItem(globals, pathstr); if (modpath != NULL) { /* __path__ is set, so modname is already the package name */ - char *modname_str; - Py_ssize_t len; int error; - modname_str = _PyUnicode_AsStringAndSize(modname, &len); - if (len > MAXPATHLEN) { + if (PyUnicode_GET_SIZE(modname)+1 > bufsize) { PyErr_SetString(PyExc_ValueError, "Module name too long"); return NULL; } - strcpy(buf, modname_str); + Py_UNICODE_strcpy(name, PyUnicode_AS_UNICODE(modname)); error = PyDict_SetItem(globals, pkgstr, modname); if (error) { PyErr_SetString(PyExc_ValueError, @@ -2824,9 +2860,9 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) } } else { /* Normal module, so work out the package name if any */ - char *start = _PyUnicode_AsString(modname); - char *lastdot = strrchr(start, '.'); - size_t len; + Py_UNICODE *start = PyUnicode_AS_UNICODE(modname); + Py_UNICODE *lastdot = Py_UNICODE_strrchr(start, '.'); + Py_ssize_t len; int error; if (lastdot == NULL && level > 0) { PyErr_SetString(PyExc_ValueError, @@ -2840,17 +2876,17 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) "Could not set __package__"); return NULL; } - return Py_None; + goto return_none; } len = lastdot - start; - if (len >= MAXPATHLEN) { + if (len+1 > bufsize) { PyErr_SetString(PyExc_ValueError, "Module name too long"); return NULL; } - strncpy(buf, start, len); - buf[len] = '\0'; - pkgname = PyUnicode_FromString(buf); + Py_UNICODE_strncpy(name, start, len); + name[len] = '\0'; + pkgname = PyUnicode_FromUnicode(name, len); if (pkgname == NULL) { return NULL; } @@ -2864,7 +2900,7 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) } } while (--level > 0) { - char *dot = strrchr(buf, '.'); + Py_UNICODE *dot = Py_UNICODE_strrchr(name, '.'); if (dot == NULL) { PyErr_SetString(PyExc_ValueError, "Attempted relative import beyond " @@ -2873,137 +2909,181 @@ get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level) } *dot = '\0'; } - *p_buflen = strlen(buf); + + nameobj = PyUnicode_FromUnicode(name, Py_UNICODE_strlen(name)); + if (nameobj == NULL) + return NULL; modules = PyImport_GetModuleDict(); - parent = PyDict_GetItemString(modules, buf); + parent = PyDict_GetItem(modules, nameobj); if (parent == NULL) { - if (orig_level < 1) { - PyObject *err_msg = PyBytes_FromFormat( - "Parent module '%.200s' not found " - "while handling absolute import", buf); - if (err_msg == NULL) { - return NULL; - } - if (!PyErr_WarnEx(PyExc_RuntimeWarning, - PyBytes_AsString(err_msg), 1)) { - *buf = '\0'; - *p_buflen = 0; - parent = Py_None; - } - Py_DECREF(err_msg); - } else { + int err; + + if (orig_level >= 1) { PyErr_Format(PyExc_SystemError, - "Parent module '%.200s' not loaded, " - "cannot perform relative import", buf); + "Parent module %R not loaded, " + "cannot perform relative import", nameobj); + Py_DECREF(nameobj); + return NULL; } + + err = PyErr_WarnFormat( + PyExc_RuntimeWarning, 1, + "Parent module %R not found while handling absolute import", + nameobj); + Py_DECREF(nameobj); + if (err) + return NULL; + + goto return_none; } + *p_name = nameobj; return parent; /* We expect, but can't guarantee, if parent != None, that: - - parent.__name__ == buf + - parent.__name__ == name - parent.__dict__ is globals If this is violated... Who cares? */ + +return_none: + nameobj = PyUnicode_FromUnicode(NULL, 0); + if (nameobj == NULL) + return NULL; + *p_name = nameobj; + return Py_None; } /* altmod is either None or same as mod */ static PyObject * -load_next(PyObject *mod, PyObject *altmod, char **p_name, char *buf, - Py_ssize_t *p_buflen) +load_next(PyObject *mod, PyObject *altmod, + PyObject *inputname, PyObject **p_outputname, + Py_UNICODE *buf, Py_ssize_t *p_buflen, Py_ssize_t bufsize) { - char *name = *p_name; - char *dot = strchr(name, '.'); - size_t len; - char *p; - PyObject *result; + const Py_UNICODE *dot; + Py_ssize_t len; + Py_UNICODE *p; + PyObject *fullname, *name, *result, *mark_name; + const Py_UNICODE *nameuni; + + *p_outputname = NULL; - if (strlen(name) == 0) { + if (PyUnicode_GET_SIZE(inputname) == 0) { /* completely empty module name should only happen in 'from . import' (or '__import__("")')*/ Py_INCREF(mod); - *p_name = NULL; return mod; } - if (dot == NULL) { - *p_name = NULL; - len = strlen(name); - } - else { - *p_name = dot+1; - len = dot-name; + nameuni = PyUnicode_AS_UNICODE(inputname); + if (nameuni == NULL) + return NULL; + + dot = Py_UNICODE_strchr(nameuni, '.'); + if (dot != NULL) { + len = dot - nameuni; + if (len == 0) { + PyErr_SetString(PyExc_ValueError, + "Empty module name"); + return NULL; + } } - if (len == 0) { + else + len = PyUnicode_GET_SIZE(inputname); + + if (*p_buflen+len+1 >= bufsize) { PyErr_SetString(PyExc_ValueError, - "Empty module name"); + "Module name too long"); return NULL; } p = buf + *p_buflen; - if (p != buf) + if (p != buf) { *p++ = '.'; - if (p+len-buf >= MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; + *p_buflen += 1; } - strncpy(p, name, len); + Py_UNICODE_strncpy(p, nameuni, len); p[len] = '\0'; - *p_buflen = p+len-buf; + *p_buflen += len; - result = import_submodule(mod, p, buf); + fullname = PyUnicode_FromUnicode(buf, *p_buflen); + if (fullname == NULL) + return NULL; + name = PyUnicode_FromUnicode(p, len); + if (name == NULL) { + Py_DECREF(fullname); + return NULL; + } + result = import_submodule(mod, name, fullname); + Py_DECREF(fullname); if (result == Py_None && altmod != mod) { Py_DECREF(result); /* Here, altmod must be None and mod must not be None */ - result = import_submodule(altmod, p, p); + result = import_submodule(altmod, name, name); + Py_DECREF(name); if (result != NULL && result != Py_None) { - if (mark_miss(buf) != 0) { + mark_name = PyUnicode_FromUnicode(buf, *p_buflen); + if (mark_name == NULL) { + Py_DECREF(result); + return NULL; + } + if (mark_miss(mark_name) != 0) { Py_DECREF(result); + Py_DECREF(mark_name); return NULL; } - strncpy(buf, name, len); + Py_DECREF(mark_name); + Py_UNICODE_strncpy(buf, nameuni, len); buf[len] = '\0'; *p_buflen = len; } } + else + Py_DECREF(name); if (result == NULL) return NULL; if (result == Py_None) { Py_DECREF(result); PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); + "No module named %R", inputname); return NULL; } + if (dot != NULL) { + *p_outputname = PyUnicode_FromUnicode(dot+1, Py_UNICODE_strlen(dot+1)); + if (*p_outputname == NULL) { + Py_DECREF(result); + return NULL; + } + } + return result; } static int -mark_miss(char *name) +mark_miss(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); - return PyDict_SetItemString(modules, name, Py_None); + return PyDict_SetItem(modules, name, Py_None); } static int -ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, +ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, int recursive) { int i; + PyObject *fullname; + Py_ssize_t fromlist_len; if (!PyObject_HasAttrString(mod, "__path__")) return 1; - for (i = 0; ; i++) { + fromlist_len = PySequence_Size(fromlist); + + for (i = 0; i < fromlist_len; i++) { PyObject *item = PySequence_GetItem(fromlist, i); int hasit; - if (item == NULL) { - if (PyErr_ExceptionMatches(PyExc_IndexError)) { - PyErr_Clear(); - return 1; - } + if (item == NULL) return 0; - } if (!PyUnicode_Check(item)) { PyErr_SetString(PyExc_TypeError, "Item in ``from list'' not a string"); @@ -3020,7 +3100,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, if (all == NULL) PyErr_Clear(); else { - int ret = ensure_fromlist(mod, all, buf, buflen, 1); + int ret = ensure_fromlist(mod, all, name, 1); Py_DECREF(all); if (!ret) return 0; @@ -3029,27 +3109,14 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, } hasit = PyObject_HasAttr(mod, item); if (!hasit) { - PyObject *item8; - char *subname; PyObject *submod; - char *p; - item8 = PyUnicode_EncodeFSDefault(item); - if (!item8) { - PyErr_SetString(PyExc_ValueError, "Cannot encode path item"); - return 0; + fullname = PyUnicode_FromFormat("%U.%U", name, item); + if (fullname != NULL) { + submod = import_submodule(mod, item, fullname); + Py_DECREF(fullname); } - subname = PyBytes_AS_STRING(item8); - if (buflen + strlen(subname) >= MAXPATHLEN) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - Py_DECREF(item); - return 0; - } - p = buf + buflen; - *p++ = '.'; - strcpy(p, subname); - submod = import_submodule(mod, subname, buf); - Py_DECREF(item8); + else + submod = NULL; Py_XDECREF(submod); if (submod == NULL) { Py_DECREF(item); @@ -3059,12 +3126,12 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, char *buf, Py_ssize_t buflen, Py_DECREF(item); } - /* NOTREACHED */ + return 1; } static int -add_submodule(PyObject *mod, PyObject *submod, char *fullname, char *subname, - PyObject *modules) +add_submodule(PyObject *mod, PyObject *submod, PyObject *fullname, + PyObject *subname, PyObject *modules) { if (mod == Py_None) return 1; @@ -3075,7 +3142,7 @@ add_submodule(PyObject *mod, PyObject *submod, char *fullname, char *subname, load failed with a SyntaxError -- then there's no trace in sys.modules. In that case, of course, do nothing extra.) */ if (submod == NULL) { - submod = PyDict_GetItemString(modules, fullname); + submod = PyDict_GetItem(modules, fullname); if (submod == NULL) return 1; } @@ -3086,28 +3153,28 @@ add_submodule(PyObject *mod, PyObject *submod, char *fullname, char *subname, PyObject *dict = PyModule_GetDict(mod); if (!dict) return 0; - if (PyDict_SetItemString(dict, subname, submod) < 0) + if (PyDict_SetItem(dict, subname, submod) < 0) return 0; } else { - if (PyObject_SetAttrString(mod, subname, submod) < 0) + if (PyObject_SetAttr(mod, subname, submod) < 0) return 0; } return 1; } static PyObject * -import_submodule(PyObject *mod, char *subname, char *fullname) +import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) { PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL, *fullnameobj, *bufobj; + PyObject *m = NULL, *bufobj; /* Require: if mod == None: subname == fullname else: mod.__name__ + "." + subname == fullname */ - if ((m = PyDict_GetItemString(modules, fullname)) != NULL) { + if ((m = PyDict_GetItem(modules, fullname)) != NULL) { Py_INCREF(m); } else { @@ -3127,7 +3194,9 @@ import_submodule(PyObject *mod, char *subname, char *fullname) } } - fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1, + fdp = find_module(_PyUnicode_AsString(fullname), + _PyUnicode_AsString(subname), + path, buf, MAXPATHLEN+1, &fp, &loader); Py_XDECREF(path); if (fdp == NULL) { @@ -3137,23 +3206,17 @@ import_submodule(PyObject *mod, char *subname, char *fullname) Py_INCREF(Py_None); return Py_None; } - fullnameobj = PyUnicode_FromString(fullname); - if (fullnameobj != NULL) { - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - m = load_module(fullnameobj, fp, bufobj, fdp->type, loader); - Py_DECREF(bufobj); - } - else - m = NULL; - Py_DECREF(fullnameobj); + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + m = load_module(fullname, fp, bufobj, fdp->type, loader); + Py_DECREF(bufobj); } else m = NULL; Py_XDECREF(loader); if (fp) fclose(fp); - if (!add_submodule(mod, m, fullname, subname, modules)) { + if (m != NULL && !add_submodule(mod, m, fullname, subname, modules)) { Py_XDECREF(m); m = NULL; } -- cgit v1.2.1 From 74c6f0ba2d358a8d6717772150740b5f49142711 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Mar 2011 22:38:06 -0400 Subject: Issue #3080: Use %R to format module name in error messages %R format instead of %U --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 95faeee5d8..90ba4b5e22 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2620,7 +2620,7 @@ PyImport_ImportModuleNoBlock(const char *name) } else { PyErr_Format(PyExc_ImportError, - "Failed to import %U because the import lock" + "Failed to import %R because the import lock" "is held by another thread.", nameobj); result = NULL; @@ -3285,7 +3285,7 @@ PyImport_ReloadModule(PyObject *m) parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { PyErr_Format(PyExc_ImportError, - "reload(): parent %U not in sys.modules", + "reload(): parent %R not in sys.modules", parentname); Py_DECREF(parentname); imp_modules_reloading_clear(); -- cgit v1.2.1 From ec2c770704d651436f9217bf78ef289f63162209 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Mar 2011 22:38:38 -0400 Subject: Issue #3080: Reindent and simplify import_submodule() --- Python/import.c | 81 +++++++++++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 42 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 90ba4b5e22..cce2de1b44 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2779,9 +2779,7 @@ PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, corresponding entry is not found in sys.modules, Py_None is returned. */ static PyObject * -get_parent(PyObject *globals, - PyObject **p_name, - int level) +get_parent(PyObject *globals, PyObject **p_name, int level) { Py_UNICODE name[MAXPATHLEN+1]; const Py_ssize_t bufsize = MAXPATHLEN+1; @@ -3167,7 +3165,10 @@ static PyObject * import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) { PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL, *bufobj; + PyObject *m = NULL, *bufobj, *path, *loader; + char buf[MAXPATHLEN+1]; + struct filedescr *fdp; + FILE *fp; /* Require: if mod == None: subname == fullname @@ -3176,52 +3177,48 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) if ((m = PyDict_GetItem(modules, fullname)) != NULL) { Py_INCREF(m); + return m; } - else { - PyObject *path, *loader; - char buf[MAXPATHLEN+1]; - struct filedescr *fdp; - FILE *fp; - - if (mod == Py_None) - path = NULL; - else { - path = PyObject_GetAttrString(mod, "__path__"); - if (path == NULL) { - PyErr_Clear(); - Py_INCREF(Py_None); - return Py_None; - } - } - fdp = find_module(_PyUnicode_AsString(fullname), - _PyUnicode_AsString(subname), - path, buf, MAXPATHLEN+1, - &fp, &loader); - Py_XDECREF(path); - if (fdp == NULL) { - if (!PyErr_ExceptionMatches(PyExc_ImportError)) - return NULL; + if (mod == Py_None) + path = NULL; + else { + path = PyObject_GetAttrString(mod, "__path__"); + if (path == NULL) { PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - m = load_module(fullname, fp, bufobj, fdp->type, loader); - Py_DECREF(bufobj); - } - else - m = NULL; - Py_XDECREF(loader); - if (fp) - fclose(fp); - if (m != NULL && !add_submodule(mod, m, fullname, subname, modules)) { - Py_XDECREF(m); - m = NULL; - } } + fdp = find_module(_PyUnicode_AsString(fullname), + _PyUnicode_AsString(subname), + path, buf, MAXPATHLEN+1, + &fp, &loader); + Py_XDECREF(path); + if (fdp == NULL) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + return NULL; + PyErr_Clear(); + Py_INCREF(Py_None); + return Py_None; + } + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + m = load_module(fullname, fp, bufobj, fdp->type, loader); + Py_DECREF(bufobj); + } + else + m = NULL; + Py_XDECREF(loader); + if (fp) + fclose(fp); + if (m == NULL) + return NULL; + if (!add_submodule(mod, m, fullname, subname, modules)) { + Py_XDECREF(m); + return NULL; + } return m; } -- cgit v1.2.1 From 7b12e183cf51fb59b0d62f26e37f91ec881a0dd9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 13 Mar 2011 23:11:02 -0400 Subject: Issue #3080: Drop OS/2 support for the import machinery Sorry Andrew I MacIntyre! --- Python/import.c | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index cce2de1b44..e6d7c060fe 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1804,11 +1804,6 @@ find_module_path_list(char *fullname, const char *name, struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; -#if defined(PYOS_OS2) - size_t saved_len; - size_t saved_namelen; - char *saved_buf = NULL; -#endif npath = PyList_Size(search_path_list); namelen = strlen(name); @@ -1832,40 +1827,7 @@ find_module_path_list(char *fullname, const char *name, return fdp; len = strlen(buf); -#if defined(PYOS_OS2) - /* take a snapshot of the module spec for restoration - * after the 8 character DLL hackery - */ - saved_buf = strdup(buf); - saved_len = len; - saved_namelen = namelen; -#endif /* PYOS_OS2 */ for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { -#if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING) - /* OS/2 limits DLLs to 8 character names (w/o - extension) - * so if the name is longer than that and its a - * dynamically loaded module we're going to try, - * truncate the name before trying - */ - if (strlen(name) > 8) { - /* is this an attempt to load a C extension? */ - const struct filedescr *scan; - scan = _PyImport_DynLoadFiletab; - while (scan->suffix != NULL) { - if (!strcmp(scan->suffix, fdp->suffix)) - break; - else - scan++; - } - if (scan->suffix != NULL) { - /* yes, so truncate the name */ - namelen = 8; - len -= strlen(name) - namelen; - buf[len] = '\0'; - } - } -#endif /* PYOS_OS2 */ strcpy(buf+len, fdp->suffix); if (Py_VerboseFlag > 1) PySys_WriteStderr("# trying %s\n", buf); @@ -1881,21 +1843,7 @@ find_module_path_list(char *fullname, const char *name, fp = NULL; } } -#if defined(PYOS_OS2) - /* restore the saved snapshot */ - strcpy(buf, saved_buf); - len = saved_len; - namelen = saved_namelen; -#endif - } -#if defined(PYOS_OS2) - /* don't need/want the module name snapshot anymore */ - if (saved_buf) - { - free(saved_buf); - saved_buf = NULL; } -#endif if (fp != NULL) break; } -- cgit v1.2.1 From e7fd2eaecbfdc259fc9ae199608d33d721d88f57 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 09:21:33 -0400 Subject: Issue #3080: find_module() expects module fullname and subname as Unicode And PyImport_ReloadModule() uses Unicode for the module name. --- Python/import.c | 170 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 84 insertions(+), 86 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e6d7c060fe..a3f263146c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1491,7 +1491,7 @@ unchanged: /* Forward */ static PyObject *load_module(PyObject *, FILE *, PyObject *, int, PyObject *); -static struct filedescr *find_module(char *, const char *, PyObject *, +static struct filedescr *find_module(PyObject *, PyObject *, PyObject *, char *, size_t, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); @@ -1507,7 +1507,13 @@ load_package(PyObject *name, PyObject *pathname) char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; - char *namestr; + static PyObject *initstr = NULL; + + if (initstr == NULL) { + initstr = PyUnicode_InternFromString("__init__"); + if (initstr == NULL) + return NULL; + } m = PyImport_AddModuleObject(name); if (m == NULL) @@ -1532,10 +1538,7 @@ load_package(PyObject *name, PyObject *pathname) Py_DECREF(path_list); return NULL; } - namestr = _PyUnicode_AsString(name); - if (namestr == NULL) - goto error; - fdp = find_module(namestr, "__init__", path_list, buf, sizeof(buf), &fp, NULL); + fdp = find_module(name, initstr, path_list, buf, sizeof(buf), &fp, NULL); Py_DECREF(path_list); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { @@ -1680,7 +1683,7 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; and *buf is the path */ static int -find_module_path(char *fullname, const char *name, PyObject *path, +find_module_path(PyObject *fullname, PyObject *name, PyObject *path, PyObject *path_hooks, PyObject *path_importer_cache, char *buf, size_t buflen, PyObject **p_loader, struct filedescr **p_fd) @@ -1691,6 +1694,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, size_t namelen; struct stat statbuf; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; + char *namestr; if (PyUnicode_Check(path)) { path_bytes = PyUnicode_EncodeFSDefault(path); @@ -1704,7 +1708,8 @@ find_module_path(char *fullname, const char *name, PyObject *path, else return 0; - namelen = strlen(name); + namestr = _PyUnicode_AsString(name); + namelen = strlen(namestr); base = PyBytes_AS_STRING(path_bytes); len = PyBytes_GET_SIZE(path_bytes); if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { @@ -1731,8 +1736,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, if (importer != Py_None) { PyObject *loader; loader = PyObject_CallMethod(importer, - "find_module", - "s", fullname); + "find_module", "O", fullname); if (loader == NULL) return -1; /* error */ if (loader != Py_None) { @@ -1753,7 +1757,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, #endif ) buf[len++] = SEP; - strcpy(buf+len, name); + strcpy(buf+len, namestr); len += namelen; /* Check for package import (buf holds a directory name, @@ -1761,7 +1765,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, #ifdef HAVE_STAT if (stat(buf, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode) && /* it's a directory */ - case_ok(buf, len, namelen, name)) { /* case matches */ + case_ok(buf, len, namelen, namestr)) { /* case matches */ if (find_init_module(buf)) { /* and has __init__.py */ *p_fd = &fd_package; return 2; @@ -1784,7 +1788,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, } /* Find a module in search_path_list. For each path, try - find_module_filename() or try each _PyImport_Filetab suffix. + find_module_path() or try each _PyImport_Filetab suffix. If the module is found, return a file descriptor, write the path in *p_filename, write the pointer to the file object into *p_fp, and (if @@ -1793,7 +1797,7 @@ find_module_path(char *fullname, const char *name, PyObject *path, Otherwise, raise an exception and return NULL. */ static struct filedescr* -find_module_path_list(char *fullname, const char *name, +find_module_path_list(PyObject *fullname, PyObject *name, PyObject *search_path_list, PyObject *path_hooks, PyObject *path_importer_cache, char *buf, size_t buflen, @@ -1804,9 +1808,11 @@ find_module_path_list(char *fullname, const char *name, struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; + char *namestr; npath = PyList_Size(search_path_list); - namelen = strlen(name); + namestr = _PyUnicode_AsString(name); + namelen = strlen(namestr); for (i = 0; i < npath; i++) { PyObject *path; int ok; @@ -1836,7 +1842,7 @@ find_module_path_list(char *fullname, const char *name, filemode = "r" PY_STDIOTEXTMODE; fp = fopen(buf, filemode); if (fp != NULL) { - if (case_ok(buf, len, namelen, name)) + if (case_ok(buf, len, namelen, namestr)) break; else { /* continue search */ fclose(fp); @@ -1849,7 +1855,7 @@ find_module_path_list(char *fullname, const char *name, } if (fp == NULL) { PyErr_Format(PyExc_ImportError, - "No module named %.200s", name); + "No module named %U", name); return NULL; } *p_fp = fp; @@ -1882,21 +1888,20 @@ find_module_path_list(char *fullname, const char *name, set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ static struct filedescr * -find_module(char *fullname, const char *name, PyObject *search_path_list, +find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; static struct filedescr fd_frozen = {"", "", PY_FROZEN}; static struct filedescr fd_builtin = {"", "", C_BUILTIN}; PyObject *path_hooks, *path_importer_cache; - PyObject *fullname_obj, *nameobj; *buf = '\0'; *p_fp = NULL; if (p_loader != NULL) *p_loader = NULL; - if (strlen(name) > MAXPATHLEN) { + if (PyUnicode_GET_SIZE(name) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, "module name is too long"); return NULL; @@ -1919,7 +1924,7 @@ find_module(char *fullname, const char *name, PyObject *search_path_list, PyObject *loader; PyObject *hook = PyList_GetItem(meta_path, i); loader = PyObject_CallMethod(hook, "find_module", - "sO", fullname, + "OO", fullname, search_path_list != NULL ? search_path_list : Py_None); if (loader == NULL) { @@ -1937,16 +1942,9 @@ find_module(char *fullname, const char *name, PyObject *search_path_list, Py_DECREF(meta_path); } - if (fullname != NULL) { - fullname_obj = PyUnicode_FromString(fullname); - if (fullname == NULL) - return NULL; - if (find_frozen(fullname_obj) != NULL) { - Py_DECREF(fullname_obj); - strcpy(buf, fullname); - return &fd_frozen; - } - Py_DECREF(fullname_obj); + if (find_frozen(fullname) != NULL) { + strcpy(buf, _PyUnicode_AsString(fullname)); + return &fd_frozen; } if (search_path_list == NULL) { @@ -1955,18 +1953,13 @@ find_module(char *fullname, const char *name, PyObject *search_path_list, struct filedescr *fdp; PyObject *filename, *filename_bytes; #endif - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - return NULL; - if (is_builtin(nameobj)) { - Py_DECREF(nameobj); - strcpy(buf, name); + if (is_builtin(name)) { + strcpy(buf, _PyUnicode_AsString(name)); return &fd_builtin; } #ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(nameobj, &fdp, &filename); + fp = _PyWin_FindRegisteredModule(name, &fdp, &filename); if (fp != NULL) { - Py_DECREF(nameobj); filename_bytes = PyUnicode_EncodeFSDefault(filename); Py_DECREF(filename); if (filename_bytes == NULL) @@ -1980,7 +1973,6 @@ find_module(char *fullname, const char *name, PyObject *search_path_list, else if (PyErr_Occurred()) return NULL; #endif - Py_DECREF(nameobj); search_path_list = PySys_GetObject("path"); } @@ -3139,8 +3131,8 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) } } - fdp = find_module(_PyUnicode_AsString(fullname), - _PyUnicode_AsString(subname), + fdp = find_module(fullname, + subname, path, buf, MAXPATHLEN+1, &fp, &loader); Py_XDECREF(path); @@ -3180,12 +3172,13 @@ PyImport_ReloadModule(PyObject *m) PyInterpreterState *interp = PyThreadState_Get()->interp; PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - PyObject *path = NULL, *loader, *existing_m = NULL; - char *name, *subname; char buf[MAXPATHLEN+1]; + PyObject *path = NULL, *loader = NULL, *existing_m = NULL; + PyObject *nameobj, *bufobj, *subnameobj; + Py_UNICODE *name, *subname; struct filedescr *fdp; - FILE *fp; - PyObject *newm, *nameobj, *bufobj; + FILE *fp = NULL; + PyObject *newm = NULL; if (modules_reloading == NULL) { Py_FatalError("PyImport_ReloadModule: " @@ -3198,69 +3191,75 @@ PyImport_ReloadModule(PyObject *m) "reload() argument must be module"); return NULL; } - name = (char*)PyModule_GetName(m); - if (name == NULL) + nameobj = PyModule_GetNameObject(m); + if (nameobj == NULL) return NULL; - if (m != PyDict_GetItemString(modules, name)) { + if (m != PyDict_GetItem(modules, nameobj)) { PyErr_Format(PyExc_ImportError, - "reload(): module %.200s not in sys.modules", - name); + "reload(): module %U not in sys.modules", + nameobj); + Py_DECREF(nameobj); return NULL; } - existing_m = PyDict_GetItemString(modules_reloading, name); + existing_m = PyDict_GetItem(modules_reloading, nameobj); if (existing_m != NULL) { /* Due to a recursive reload, this module is already being reloaded. */ + Py_DECREF(nameobj); Py_INCREF(existing_m); return existing_m; } - if (PyDict_SetItemString(modules_reloading, name, m) < 0) + if (PyDict_SetItem(modules_reloading, nameobj, m) < 0) { + Py_DECREF(nameobj); return NULL; + } - subname = strrchr(name, '.'); - if (subname == NULL) - subname = name; + name = PyUnicode_AS_UNICODE(nameobj); + subname = Py_UNICODE_strrchr(name, '.'); + if (subname == NULL) { + Py_INCREF(nameobj); + subnameobj = nameobj; + } else { PyObject *parentname, *parent; - parentname = PyUnicode_FromStringAndSize(name, (subname-name)); + Py_ssize_t len; + len = subname - name; + parentname = PyUnicode_FromUnicode(name, len); if (parentname == NULL) { - imp_modules_reloading_clear(); - return NULL; + goto error; } parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { PyErr_Format(PyExc_ImportError, - "reload(): parent %R not in sys.modules", + "reload(): parent %U not in sys.modules", parentname); Py_DECREF(parentname); - imp_modules_reloading_clear(); - return NULL; + goto error; } Py_DECREF(parentname); - subname++; path = PyObject_GetAttrString(parent, "__path__"); if (path == NULL) PyErr_Clear(); + subname++; + len = PyUnicode_GET_SIZE(nameobj) - (len + 1); + subnameobj = PyUnicode_FromUnicode(subname, len); } - fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader); + if (subnameobj == NULL) + goto error; + fdp = find_module(nameobj, subnameobj, + path, buf, MAXPATHLEN+1, &fp, &loader); + Py_DECREF(subnameobj); Py_XDECREF(path); if (fdp == NULL) { Py_XDECREF(loader); - imp_modules_reloading_clear(); - return NULL; + goto error; } - nameobj = PyUnicode_FromString(name); - if (nameobj != NULL) { - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - newm = load_module(nameobj, fp, bufobj, fdp->type, loader); - Py_DECREF(bufobj); - } - else - newm = NULL; - Py_DECREF(nameobj); + bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj != NULL) { + newm = load_module(nameobj, fp, bufobj, fdp->type, loader); + Py_DECREF(bufobj); } else newm = NULL; @@ -3274,9 +3273,12 @@ PyImport_ReloadModule(PyObject *m) * going to return NULL in this case regardless of whether * replacing name succeeds, so the return value is ignored. */ - PyDict_SetItemString(modules, name, m); + PyDict_SetItem(modules, nameobj, m); } + +error: imp_modules_reloading_clear(); + Py_DECREF(nameobj); return newm; } @@ -3424,7 +3426,7 @@ imp_get_suffixes(PyObject *self, PyObject *noargs) } static PyObject * -call_find_module(char *name, PyObject *path) +call_find_module(PyObject *name, PyObject *path) { extern int fclose(FILE *); PyObject *fob, *ret; @@ -3483,15 +3485,11 @@ call_find_module(char *name, PyObject *path) static PyObject * imp_find_module(PyObject *self, PyObject *args) { - PyObject *name; - PyObject *ret, *path = NULL; - if (!PyArg_ParseTuple(args, "O&|O:find_module", - PyUnicode_FSConverter, &name, - &path)) + PyObject *name, *path_list = NULL; + if (!PyArg_ParseTuple(args, "U|O:find_module", + &name, &path_list)) return NULL; - ret = call_find_module(PyBytes_AS_STRING(name), path); - Py_DECREF(name); - return ret; + return call_find_module(name, path_list); } static PyObject * -- cgit v1.2.1 From c23cd9690f4b004e965101735800e7c352fcfc78 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 13:22:54 -0400 Subject: Issue #3080: Rename some path variables to path_list --- Python/import.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index a3f263146c..73d38fe10f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1538,7 +1538,8 @@ load_package(PyObject *name, PyObject *pathname) Py_DECREF(path_list); return NULL; } - fdp = find_module(name, initstr, path_list, buf, sizeof(buf), &fp, NULL); + fdp = find_module(name, initstr, path_list, + buf, sizeof(buf), &fp, NULL); Py_DECREF(path_list); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { @@ -3105,7 +3106,7 @@ static PyObject * import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) { PyObject *modules = PyImport_GetModuleDict(); - PyObject *m = NULL, *bufobj, *path, *loader; + PyObject *m = NULL, *bufobj, *path_list, *loader; char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp; @@ -3121,21 +3122,19 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) } if (mod == Py_None) - path = NULL; + path_list = NULL; else { - path = PyObject_GetAttrString(mod, "__path__"); - if (path == NULL) { + path_list = PyObject_GetAttrString(mod, "__path__"); + if (path_list == NULL) { PyErr_Clear(); Py_INCREF(Py_None); return Py_None; } } - fdp = find_module(fullname, - subname, - path, buf, MAXPATHLEN+1, - &fp, &loader); - Py_XDECREF(path); + fdp = find_module(fullname, subname, path_list, + buf, MAXPATHLEN+1, &fp, &loader); + Py_XDECREF(path_list); if (fdp == NULL) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) return NULL; @@ -3173,7 +3172,7 @@ PyImport_ReloadModule(PyObject *m) PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); char buf[MAXPATHLEN+1]; - PyObject *path = NULL, *loader = NULL, *existing_m = NULL; + PyObject *path_list = NULL, *loader = NULL, *existing_m = NULL; PyObject *nameobj, *bufobj, *subnameobj; Py_UNICODE *name, *subname; struct filedescr *fdp; @@ -3237,8 +3236,8 @@ PyImport_ReloadModule(PyObject *m) goto error; } Py_DECREF(parentname); - path = PyObject_GetAttrString(parent, "__path__"); - if (path == NULL) + path_list = PyObject_GetAttrString(parent, "__path__"); + if (path_list == NULL) PyErr_Clear(); subname++; len = PyUnicode_GET_SIZE(nameobj) - (len + 1); @@ -3246,10 +3245,10 @@ PyImport_ReloadModule(PyObject *m) } if (subnameobj == NULL) goto error; - fdp = find_module(nameobj, subnameobj, - path, buf, MAXPATHLEN+1, &fp, &loader); + fdp = find_module(nameobj, subnameobj, path_list, + buf, MAXPATHLEN+1, &fp, &loader); Py_DECREF(subnameobj); - Py_XDECREF(path); + Py_XDECREF(path_list); if (fdp == NULL) { Py_XDECREF(loader); @@ -3426,7 +3425,7 @@ imp_get_suffixes(PyObject *self, PyObject *noargs) } static PyObject * -call_find_module(PyObject *name, PyObject *path) +call_find_module(PyObject *name, PyObject *path_list) { extern int fclose(FILE *); PyObject *fob, *ret; @@ -3439,9 +3438,10 @@ call_find_module(PyObject *name, PyObject *path) char *encoding = NULL; pathname[0] = '\0'; - if (path == Py_None) - path = NULL; - fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL); + if (path_list == Py_None) + path_list = NULL; + fdp = find_module(NULL, name, path_list, + pathname, MAXPATHLEN+1, &fp, NULL); if (fdp == NULL) return NULL; if (fp != NULL) { -- cgit v1.2.1 From d5658be50acead958aef78e5c41c8d4d4bd0e857 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 13:40:04 -0400 Subject: Issue #3080: find_module() sets an empty path for builtin and frozen modules --- Python/import.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 73d38fe10f..2c21112c4b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1943,10 +1943,8 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, Py_DECREF(meta_path); } - if (find_frozen(fullname) != NULL) { - strcpy(buf, _PyUnicode_AsString(fullname)); + if (find_frozen(fullname) != NULL) return &fd_frozen; - } if (search_path_list == NULL) { #ifdef MS_COREDLL @@ -1954,10 +1952,8 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, struct filedescr *fdp; PyObject *filename, *filename_bytes; #endif - if (is_builtin(name)) { - strcpy(buf, _PyUnicode_AsString(name)); + if (is_builtin(name)) return &fd_builtin; - } #ifdef MS_COREDLL fp = _PyWin_FindRegisteredModule(name, &fdp, &filename); if (fp != NULL) { -- cgit v1.2.1 From 2c6f2066619d885ebc3fd2c23dd6ca17f18ba71c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 14:04:10 -0400 Subject: Issue #3080: Refactor find_module_path(), use return instead of break Prepare also the API change of case_ok() --- Python/import.c | 77 +++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 40 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 2c21112c4b..979058e583 100644 --- a/Python/import.c +++ b/Python/import.c @@ -144,6 +144,8 @@ static const struct filedescr _PyImport_StandardFiletab[] = { {0, 0} }; +static PyObject *initstr = NULL; + /* Initialize things */ @@ -155,6 +157,10 @@ _PyImport_Init(void) int countD = 0; int countS = 0; + initstr = PyUnicode_InternFromString("__init__"); + if (initstr == NULL) + Py_FatalError("Can't initialize import variables"); + /* prepare _PyImport_Filetab: copy entries from _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. */ @@ -1507,13 +1513,6 @@ load_package(PyObject *name, PyObject *pathname) char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; - static PyObject *initstr = NULL; - - if (initstr == NULL) { - initstr = PyUnicode_InternFromString("__init__"); - if (initstr == NULL) - return NULL; - } m = PyImport_AddModuleObject(name); if (m == NULL) @@ -1765,23 +1764,25 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, and there's an __init__ module in that directory */ #ifdef HAVE_STAT if (stat(buf, &statbuf) == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode) && /* it's a directory */ - case_ok(buf, len, namelen, namestr)) { /* case matches */ - if (find_init_module(buf)) { /* and has __init__.py */ - *p_fd = &fd_package; - return 2; - } - else { - int err; - PyObject *unicode = PyUnicode_DecodeFSDefault(buf); - if (unicode == NULL) - return -1; - err = PyErr_WarnFormat(PyExc_ImportWarning, 1, - "Not importing directory '%U': missing __init__.py", - unicode); - Py_DECREF(unicode); - if (err) - return -1; + S_ISDIR(statbuf.st_mode)) /* it's a directory */ + { + if (case_ok(buf, len, namelen, namestr)) { /* case matches */ + if (find_init_module(buf)) { /* and has __init__.py */ + *p_fd = &fd_package; + return 2; + } + else { + int err; + PyObject *unicode = PyUnicode_DecodeFSDefault(buf); + if (unicode == NULL) + return -1; + err = PyErr_WarnFormat(PyExc_ImportWarning, 1, + "Not importing directory '%U': missing __init__.py", + unicode); + Py_DECREF(unicode); + if (err) + return -1; + } } } #endif @@ -1842,25 +1843,21 @@ find_module_path_list(PyObject *fullname, PyObject *name, if (filemode[0] == 'U') filemode = "r" PY_STDIOTEXTMODE; fp = fopen(buf, filemode); - if (fp != NULL) { - if (case_ok(buf, len, namelen, namestr)) - break; - else { /* continue search */ - fclose(fp); - fp = NULL; - } + if (fp == NULL) + continue; + + if (case_ok(buf, len, namelen, namestr)) { + *p_fp = fp; + return fdp; } + + fclose(fp); + fp = NULL; } - if (fp != NULL) - break; - } - if (fp == NULL) { - PyErr_Format(PyExc_ImportError, - "No module named %U", name); - return NULL; } - *p_fp = fp; - return fdp; + PyErr_Format(PyExc_ImportError, + "No module named %U", name); + return NULL; } /* Find a module: -- cgit v1.2.1 From 87e72d7343dc9ff213470b182fbba2bd73e7a6d1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 03:07:28 +0100 Subject: Issue #3080: find_init_module() expects Unicode --- Python/import.c | 88 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 979058e583..8a242a57eb 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1668,8 +1668,9 @@ extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, PyObject **p_path); #endif +/* Forward */ static int case_ok(char *, Py_ssize_t, Py_ssize_t, const char *); -static int find_init_module(char *); /* Forward */ +static int find_init_module(PyObject *); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; /* Get the path of a module: get its importer and call importer.find_module() @@ -1766,24 +1767,27 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, if (stat(buf, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode)) /* it's a directory */ { + PyObject *bufobj = PyUnicode_DecodeFSDefault(buf); + if (bufobj == NULL) + return -1; if (case_ok(buf, len, namelen, namestr)) { /* case matches */ - if (find_init_module(buf)) { /* and has __init__.py */ + if (find_init_module(bufobj)) { /* and has __init__.py */ + Py_DECREF(bufobj); *p_fd = &fd_package; return 2; } else { int err; - PyObject *unicode = PyUnicode_DecodeFSDefault(buf); - if (unicode == NULL) - return -1; err = PyErr_WarnFormat(PyExc_ImportWarning, 1, - "Not importing directory '%U': missing __init__.py", - unicode); - Py_DECREF(unicode); - if (err) + "Not importing directory %R: missing __init__.py", + bufobj); + if (err) { + Py_DECREF(bufobj); return -1; + } } } + Py_DECREF(bufobj); } #endif return 1; @@ -2154,49 +2158,47 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) #ifdef HAVE_STAT -/* Helper to look for __init__.py or __init__.py[co] in potential package */ +/* Helper to look for __init__.py or __init__.py[co] in potential package. + Return 1 if __init__ was found, 0 if not, or -1 on error. */ static int -find_init_module(char *buf) +find_init_module(PyObject *directory) { - const size_t save_len = strlen(buf); - size_t i = save_len; - char *pname; /* pointer to start of __init__ */ + size_t len; struct stat statbuf; - -/* For calling case_ok(buf, len, namelen, name): - * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0 - * ^ ^ ^ ^ - * |--------------------- buf ---------------------| - * |------------------- len ------------------| - * |------ name -------| - * |----- namelen -----| - */ - if (save_len + 13 >= MAXPATHLEN) - return 0; - buf[i++] = SEP; - pname = buf + i; - strcpy(pname, "__init__.py"); - if (stat(buf, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; + PyObject *filename; + int match; + char *filestr; + size_t filelen; + + len = PyUnicode_GET_SIZE(directory); + filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); + if (filename == NULL) + return -1; + if (_Py_stat(filename, &statbuf) == 0) { + /* 9=len("/__init__") */ + filestr = _PyUnicode_AsString(filename); + filelen = strlen(filestr); + if (case_ok(filestr, filelen-9, 8, "__init__")) { + Py_DECREF(filename); return 1; } } - i += strlen(pname); - strcpy(buf+i, Py_OptimizeFlag ? "o" : "c"); - if (stat(buf, &statbuf) == 0) { - if (case_ok(buf, - save_len + 9, /* len("/__init__") */ - 8, /* len("__init__") */ - pname)) { - buf[save_len] = '\0'; + Py_DECREF(filename); + + filename = PyUnicode_FromFormat("%U%c__init__.py%c", + directory, SEP, Py_OptimizeFlag ? 'o' : 'c'); + if (filename == NULL) + return -1; + if (_Py_stat(filename, &statbuf) == 0) { + /* 9=len("/__init__") */ + filestr = _PyUnicode_AsString(filename); + filelen = strlen(filestr); + if (case_ok(filestr, filelen-9, 8, "__init__")) { + Py_DECREF(filename); return 1; } } - buf[save_len] = '\0'; + Py_DECREF(filename); return 0; } -- cgit v1.2.1 From 7bca4dba35971a2705590aee419a18ad29fefd06 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 14:34:13 -0400 Subject: Issue #3080: case_ok() expects Unicode strings --- Python/import.c | 181 +++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 132 insertions(+), 49 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 8a242a57eb..bba0120321 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1669,7 +1669,7 @@ extern FILE *_PyWin_FindRegisteredModule(PyObject *, struct filedescr **, #endif /* Forward */ -static int case_ok(char *, Py_ssize_t, Py_ssize_t, const char *); +static int case_ok(PyObject *, Py_ssize_t, PyObject *); static int find_init_module(PyObject *); static struct filedescr importhookdescr = {"", "", IMP_HOOK}; @@ -1767,12 +1767,20 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, if (stat(buf, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode)) /* it's a directory */ { - PyObject *bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj == NULL) + int match; + PyObject *filename; + + filename = PyUnicode_DecodeFSDefault(buf); + if (filename == NULL) + return -1; + match = case_ok(filename, 0, name); + if (match < 0) { + Py_DECREF(filename); return -1; - if (case_ok(buf, len, namelen, namestr)) { /* case matches */ - if (find_init_module(bufobj)) { /* and has __init__.py */ - Py_DECREF(bufobj); + } + if (match) { /* case matches */ + if (find_init_module(filename)) { /* and has __init__.py */ + Py_DECREF(filename); *p_fd = &fd_package; return 2; } @@ -1780,14 +1788,14 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, int err; err = PyErr_WarnFormat(PyExc_ImportWarning, 1, "Not importing directory %R: missing __init__.py", - bufobj); + filename); if (err) { - Py_DECREF(bufobj); + Py_DECREF(filename); return -1; } } } - Py_DECREF(bufobj); + Py_DECREF(filename); } #endif return 1; @@ -1815,6 +1823,8 @@ find_module_path_list(PyObject *fullname, PyObject *name, char *filemode; FILE *fp = NULL; char *namestr; + PyObject *filename; + int match; npath = PyList_Size(search_path_list); namestr = _PyUnicode_AsString(name); @@ -1840,20 +1850,34 @@ find_module_path_list(PyObject *fullname, PyObject *name, len = strlen(buf); for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { - strcpy(buf+len, fdp->suffix); - if (Py_VerboseFlag > 1) - PySys_WriteStderr("# trying %s\n", buf); filemode = fdp->mode; if (filemode[0] == 'U') filemode = "r" PY_STDIOTEXTMODE; - fp = fopen(buf, filemode); - if (fp == NULL) - continue; - if (case_ok(buf, len, namelen, namestr)) { + strcpy(buf+len, fdp->suffix); + filename = PyUnicode_DecodeFSDefault(buf); + if (filename == NULL) + return NULL; + + if (Py_VerboseFlag > 1) + PySys_FormatStderr("# trying %R\n", filename); + + fp = _Py_fopen(filename, filemode); + if (fp == NULL) { + Py_DECREF(filename); + continue; + } + match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name); + if (match < 0) { + Py_DECREF(filename); + return NULL; + } + if (match) { + Py_DECREF(filename); *p_fp = fp; return fdp; } + Py_DECREF(filename); fclose(fp); fp = NULL; @@ -2002,7 +2026,7 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, p_fp, p_loader); } -/* case_ok(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) +/* case_bytes(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 * ^ ^ ^ ^ @@ -2016,18 +2040,18 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, * We've already done a successful stat() or fopen() on buf, so know that * there's some match, possibly case-insensitive. * - * case_ok() is to return 1 if there's a case-sensitive match for - * name, else 0. case_ok() is also to return 1 if envar PYTHONCASEOK + * case_bytes() is to return 1 if there's a case-sensitive match for + * name, else 0. case_bytes() is also to return 1 if envar PYTHONCASEOK * exists. * - * case_ok() is used to implement case-sensitive import semantics even + * case_bytes() is used to implement case-sensitive import semantics even * on platforms with case-insensitive filesystems. It's trivial to implement * for case-sensitive filesystems. It's pretty much a cross-platform * nightmare for systems with case-insensitive filesystems. */ /* First we may need a pile of platform-specific header files; the sequence - * of #if's here should match the sequence in the body of case_ok(). + * of #if's here should match the sequence in the body of case_bytes(). */ #if defined(MS_WINDOWS) #include @@ -2046,33 +2070,24 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, #include #endif +#if defined(DJGPP) \ + || ((defined(__MACH__) && defined(__APPLE__) || defined(__CYGWIN__)) \ + && defined(HAVE_DIRENT_H)) \ + || defined(PYOS_OS2) +# define USE_CASE_OK_BYTES +#endif + + +#ifdef USE_CASE_OK_BYTES static int -case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) +case_bytes(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) { /* Pick a platform-specific implementation; the sequence of #if's here should * match the sequence just above. */ -/* MS_WINDOWS */ -#if defined(MS_WINDOWS) - WIN32_FIND_DATA data; - HANDLE h; - - if (Py_GETENV("PYTHONCASEOK") != NULL) - return 1; - - h = FindFirstFile(buf, &data); - if (h == INVALID_HANDLE_VALUE) { - PyErr_Format(PyExc_NameError, - "Can't find file for module %.100s\n(filename %.300s)", - name, buf); - return 0; - } - FindClose(h); - return strncmp(data.cFileName, name, namelen) == 0; - /* DJGPP */ -#elif defined(DJGPP) +#if defined(DJGPP) struct ffblk ffblk; int done; @@ -2151,6 +2166,70 @@ case_ok(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) /* assuming it's a case-sensitive filesystem, so there's nothing to do! */ #else +# error "USE_CASE_OK_BYTES is not correctly defined" +#endif +} +#endif + +/* + * Check if a filename case matchs the name case. We've already done a + * successful stat() or fopen() on buf, so know that there's some match, + * possibly case-insensitive. + * + * case_ok() is to return 1 if there's a case-sensitive match for name, 0 if it + * the filename doesn't match, or -1 on error. case_ok() is also to return 1 + * if envar PYTHONCASEOK exists. + * + * case_ok() is used to implement case-sensitive import semantics even + * on platforms with case-insensitive filesystems. It's trivial to implement + * for case-sensitive filesystems. It's pretty much a cross-platform + * nightmare for systems with case-insensitive filesystems. + */ + +static int +case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) +{ +#ifdef MS_WINDOWS + WIN32_FIND_DATAW data; + HANDLE h; + int cmp; + + if (Py_GETENV("PYTHONCASEOK") != NULL) + return 1; + + h = FindFirstFileW(PyUnicode_AS_UNICODE(filename), &data); + if (h == INVALID_HANDLE_VALUE) { + PyErr_Format(PyExc_NameError, + "Can't find file for module %R\n(filename %R)", + name, filename); + return 0; + } + FindClose(h); + cmp = wcsncmp(data.cFileName, + PyUnicode_AS_UNICODE(name), + PyUnicode_GET_SIZE(name)); + return cmp == 0; +#elif defined(USE_CASE_OK_BYTES) + int match; + PyObject *filebytes, *namebytes; + filebytes = PyUnicode_EncodeFSDefault(filename); + if (filebytes == NULL) + return -1; + namebytes = PyUnicode_EncodeFSDefault(name); + if (namebytes == NULL) { + Py_DECREF(filebytes); + return -1; + } + match = case_bytes( + PyBytes_AS_STRING(filebytes), + PyBytes_GET_SIZE(filebytes) + prefix_delta, + PyBytes_AS_STRING(namebytes), + PyBytes_GET_SIZE(namebytes)); + Py_DECREF(filebytes); + Py_DECREF(namebytes); + return match; +#else + /* assuming it's a case-sensitive filesystem, so there's nothing to do! */ return 1; #endif @@ -2167,8 +2246,6 @@ find_init_module(PyObject *directory) struct stat statbuf; PyObject *filename; int match; - char *filestr; - size_t filelen; len = PyUnicode_GET_SIZE(directory); filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); @@ -2176,9 +2253,12 @@ find_init_module(PyObject *directory) return -1; if (_Py_stat(filename, &statbuf) == 0) { /* 9=len("/__init__") */ - filestr = _PyUnicode_AsString(filename); - filelen = strlen(filestr); - if (case_ok(filestr, filelen-9, 8, "__init__")) { + match = case_ok(filename, 9, initstr); + if (match < 0) { + Py_DECREF(filename); + return -1; + } + if (match) { Py_DECREF(filename); return 1; } @@ -2191,9 +2271,12 @@ find_init_module(PyObject *directory) return -1; if (_Py_stat(filename, &statbuf) == 0) { /* 9=len("/__init__") */ - filestr = _PyUnicode_AsString(filename); - filelen = strlen(filestr); - if (case_ok(filestr, filelen-9, 8, "__init__")) { + match = case_ok(filename, 9, initstr); + if (match < 0) { + Py_DECREF(filename); + return -1; + } + if (match) { Py_DECREF(filename); return 1; } -- cgit v1.2.1 From 02352565abd1eed9eb32c5c273bc640869f2100b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 15:19:39 -0400 Subject: Issue #3080: find_module() returns the path as Unicode --- Python/import.c | 171 ++++++++++++++++++++++++-------------------------------- 1 file changed, 74 insertions(+), 97 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index bba0120321..5dcbf17710 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1498,7 +1498,7 @@ unchanged: /* Forward */ static PyObject *load_module(PyObject *, FILE *, PyObject *, int, PyObject *); static struct filedescr *find_module(PyObject *, PyObject *, PyObject *, - char *, size_t, FILE **, PyObject **); + PyObject **, FILE **, PyObject **); static struct _frozen * find_frozen(PyObject *); /* Load a package and return its module object WITH INCREMENTED @@ -1510,7 +1510,6 @@ load_package(PyObject *name, PyObject *pathname) PyObject *m, *d, *bufobj; PyObject *file = NULL, *path_list = NULL; int err; - char buf[MAXPATHLEN+1]; FILE *fp = NULL; struct filedescr *fdp; @@ -1538,7 +1537,7 @@ load_package(PyObject *name, PyObject *pathname) return NULL; } fdp = find_module(name, initstr, path_list, - buf, sizeof(buf), &fp, NULL); + &bufobj, &fp, NULL); Py_DECREF(path_list); if (fdp == NULL) { if (PyErr_ExceptionMatches(PyExc_ImportError)) { @@ -1549,13 +1548,8 @@ load_package(PyObject *name, PyObject *pathname) else return NULL; } - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - m = load_module(name, fp, bufobj, fdp->type, NULL); - Py_DECREF(bufobj); - } - else - m = NULL; + m = load_module(name, fp, bufobj, fdp->type, NULL); + Py_XDECREF(bufobj); if (fp != NULL) fclose(fp); return m; @@ -1686,43 +1680,40 @@ static struct filedescr importhookdescr = {"", "", IMP_HOOK}; static int find_module_path(PyObject *fullname, PyObject *name, PyObject *path, PyObject *path_hooks, PyObject *path_importer_cache, - char *buf, size_t buflen, - PyObject **p_loader, struct filedescr **p_fd) + PyObject **p_path, PyObject **p_loader, struct filedescr **p_fd) { - PyObject *path_bytes; - const char *base; + Py_UNICODE buf[MAXPATHLEN+1]; + Py_ssize_t buflen = MAXPATHLEN+1; + PyObject *path_unicode, *filename; + const Py_UNICODE *base; Py_ssize_t len; - size_t namelen; struct stat statbuf; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - char *namestr; if (PyUnicode_Check(path)) { - path_bytes = PyUnicode_EncodeFSDefault(path); - if (path_bytes == NULL) - return -1; + Py_INCREF(path); + path_unicode = path; } else if (PyBytes_Check(path)) { - Py_INCREF(path); - path_bytes = path; + path_unicode = PyUnicode_DecodeFSDefaultAndSize( + PyBytes_AS_STRING(path), PyBytes_GET_SIZE(path)); + if (path_unicode == NULL) + return -1; } else return 0; - namestr = _PyUnicode_AsString(name); - namelen = strlen(namestr); - base = PyBytes_AS_STRING(path_bytes); - len = PyBytes_GET_SIZE(path_bytes); - if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) { - Py_DECREF(path_bytes); + base = PyUnicode_AS_UNICODE(path_unicode); + len = PyUnicode_GET_SIZE(path_unicode); + if (len + 2 + PyUnicode_GET_SIZE(name) + MAXSUFFIXSIZE >= buflen) { + Py_DECREF(path_unicode); return 0; /* Too long */ } - strcpy(buf, base); - Py_DECREF(path_bytes); + Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(path_unicode)); + Py_DECREF(path_unicode); - if (strlen(buf) != len) { - return 0; /* path_bytes contains '\0' */ - } + if (Py_UNICODE_strlen(buf) != len) + return 0; /* path contains '\0' */ /* sys.path_hooks import hook */ if (p_loader != NULL) { @@ -1758,21 +1749,21 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, #endif ) buf[len++] = SEP; - strcpy(buf+len, namestr); - len += namelen; + Py_UNICODE_strcpy(buf+len, PyUnicode_AS_UNICODE(name)); + len += PyUnicode_GET_SIZE(name); + + filename = PyUnicode_FromUnicode(buf, len); + if (filename == NULL) + return -1; /* Check for package import (buf holds a directory name, and there's an __init__ module in that directory */ #ifdef HAVE_STAT - if (stat(buf, &statbuf) == 0 && /* it exists */ + if (_Py_stat(filename, &statbuf) == 0 && /* it exists */ S_ISDIR(statbuf.st_mode)) /* it's a directory */ { int match; - PyObject *filename; - filename = PyUnicode_DecodeFSDefault(buf); - if (filename == NULL) - return -1; match = case_ok(filename, 0, name); if (match < 0) { Py_DECREF(filename); @@ -1780,7 +1771,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, } if (match) { /* case matches */ if (find_init_module(filename)) { /* and has __init__.py */ - Py_DECREF(filename); + *p_path = filename; *p_fd = &fd_package; return 2; } @@ -1795,9 +1786,9 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, } } } - Py_DECREF(filename); } #endif + *p_path = filename; return 1; } @@ -1814,21 +1805,16 @@ static struct filedescr* find_module_path_list(PyObject *fullname, PyObject *name, PyObject *search_path_list, PyObject *path_hooks, PyObject *path_importer_cache, - char *buf, size_t buflen, - FILE **p_fp, PyObject **p_loader) + PyObject **p_path, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; - size_t len, namelen; struct filedescr *fdp = NULL; char *filemode; FILE *fp = NULL; - char *namestr; - PyObject *filename; + PyObject *prefix, *filename; int match; npath = PyList_Size(search_path_list); - namestr = _PyUnicode_AsString(name); - namelen = strlen(namestr); for (i = 0; i < npath; i++) { PyObject *path; int ok; @@ -1837,27 +1823,29 @@ find_module_path_list(PyObject *fullname, PyObject *name, if (path == NULL) return NULL; + prefix = NULL; ok = find_module_path(fullname, name, path, path_hooks, path_importer_cache, - buf, buflen, - p_loader, &fdp); + &prefix, p_loader, &fdp); if (ok < 0) return NULL; if (ok == 0) continue; - if (ok == 2) + if (ok == 2) { + *p_path = prefix; return fdp; + } - len = strlen(buf); for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { filemode = fdp->mode; if (filemode[0] == 'U') filemode = "r" PY_STDIOTEXTMODE; - strcpy(buf+len, fdp->suffix); - filename = PyUnicode_DecodeFSDefault(buf); - if (filename == NULL) + filename = PyUnicode_FromFormat("%U%s", prefix, fdp->suffix); + if (filename == NULL) { + Py_DECREF(prefix); return NULL; + } if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %R\n", filename); @@ -1869,11 +1857,13 @@ find_module_path_list(PyObject *fullname, PyObject *name, } match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name); if (match < 0) { + Py_DECREF(prefix); Py_DECREF(filename); return NULL; } if (match) { - Py_DECREF(filename); + Py_DECREF(prefix); + *p_path = filename; *p_fp = fp; return fdp; } @@ -1882,6 +1872,7 @@ find_module_path_list(PyObject *fullname, PyObject *name, fclose(fp); fp = NULL; } + Py_DECREF(prefix); } PyErr_Format(PyExc_ImportError, "No module named %U", name); @@ -1897,32 +1888,35 @@ find_module_path_list(PyObject *fullname, PyObject *name, - otherwise, call find_module_path_list() with search_path_list (if not NULL) or sys.path + fullname can be NULL, but only if p_loader is NULL. + Return: - &fd_builtin (C_BUILTIN) if it is a builtin - &fd_frozen (PY_FROZEN) if it is frozen - - &fd_package (PKG_DIRECTORY) and write the filename into *buf + - &fd_package (PKG_DIRECTORY) and write the filename into *p_path if it is a package - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a importer loader was found - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or PY_CODERESOURCE: see _PyImport_Filetab), write the filename into - *buf and the pointer to the open file into *p_fp + *p_path and the pointer to the open file into *p_fp - NULL on error - By default, write an empty string into *buf, and *p_fp and *p_loader (if - set) are set to NULL. Eg. *buf is an empty string for a builtin package. */ + By default, *p_path, *p_fp and *p_loader (if set) are set to NULL. + Eg. *p_path is set to NULL for a builtin package. +*/ static struct filedescr * find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, - char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader) + PyObject **p_path, FILE **p_fp, PyObject **p_loader) { Py_ssize_t i, npath; static struct filedescr fd_frozen = {"", "", PY_FROZEN}; static struct filedescr fd_builtin = {"", "", C_BUILTIN}; PyObject *path_hooks, *path_importer_cache; - *buf = '\0'; + *p_path = NULL; *p_fp = NULL; if (p_loader != NULL) *p_loader = NULL; @@ -1975,20 +1969,12 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, #ifdef MS_COREDLL FILE *fp; struct filedescr *fdp; - PyObject *filename, *filename_bytes; #endif if (is_builtin(name)) return &fd_builtin; #ifdef MS_COREDLL - fp = _PyWin_FindRegisteredModule(name, &fdp, &filename); + fp = _PyWin_FindRegisteredModule(name, &fdp, p_path); if (fp != NULL) { - filename_bytes = PyUnicode_EncodeFSDefault(filename); - Py_DECREF(filename); - if (filename_bytes == NULL) - return NULL; - strncpy(buf, PyBytes_AS_STRING(filename_bytes), buflen); - buf[buflen-1] = '\0'; - Py_DECREF(filename_bytes); *p_fp = fp; return fdp; } @@ -2022,8 +2008,7 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, return find_module_path_list(fullname, name, search_path_list, path_hooks, path_importer_cache, - buf, buflen, - p_fp, p_loader); + p_path, p_fp, p_loader); } /* case_bytes(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name) @@ -3185,7 +3170,6 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m = NULL, *bufobj, *path_list, *loader; - char buf[MAXPATHLEN+1]; struct filedescr *fdp; FILE *fp; @@ -3211,7 +3195,7 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) } fdp = find_module(fullname, subname, path_list, - buf, MAXPATHLEN+1, &fp, &loader); + &bufobj, &fp, &loader); Py_XDECREF(path_list); if (fdp == NULL) { if (!PyErr_ExceptionMatches(PyExc_ImportError)) @@ -3220,13 +3204,8 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) Py_INCREF(Py_None); return Py_None; } - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - m = load_module(fullname, fp, bufobj, fdp->type, loader); - Py_DECREF(bufobj); - } - else - m = NULL; + m = load_module(fullname, fp, bufobj, fdp->type, loader); + Py_XDECREF(bufobj); Py_XDECREF(loader); if (fp) fclose(fp); @@ -3249,7 +3228,6 @@ PyImport_ReloadModule(PyObject *m) PyInterpreterState *interp = PyThreadState_Get()->interp; PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); - char buf[MAXPATHLEN+1]; PyObject *path_list = NULL, *loader = NULL, *existing_m = NULL; PyObject *nameobj, *bufobj, *subnameobj; Py_UNICODE *name, *subname; @@ -3324,7 +3302,7 @@ PyImport_ReloadModule(PyObject *m) if (subnameobj == NULL) goto error; fdp = find_module(nameobj, subnameobj, path_list, - buf, MAXPATHLEN+1, &fp, &loader); + &bufobj, &fp, &loader); Py_DECREF(subnameobj); Py_XDECREF(path_list); @@ -3333,13 +3311,8 @@ PyImport_ReloadModule(PyObject *m) goto error; } - bufobj = PyUnicode_DecodeFSDefault(buf); - if (bufobj != NULL) { - newm = load_module(nameobj, fp, bufobj, fdp->type, loader); - Py_DECREF(bufobj); - } - else - newm = NULL; + newm = load_module(nameobj, fp, bufobj, fdp->type, loader); + Py_XDECREF(bufobj); Py_XDECREF(loader); if (fp) @@ -3509,17 +3482,15 @@ call_find_module(PyObject *name, PyObject *path_list) PyObject *fob, *ret; PyObject *pathobj; struct filedescr *fdp; - char pathname[MAXPATHLEN+1]; FILE *fp; int fd = -1; char *found_encoding = NULL; char *encoding = NULL; - pathname[0] = '\0'; if (path_list == Py_None) path_list = NULL; fdp = find_module(NULL, name, path_list, - pathname, MAXPATHLEN+1, &fp, NULL); + &pathobj, &fp, NULL); if (fdp == NULL) return NULL; if (fp != NULL) { @@ -3535,14 +3506,17 @@ call_find_module(PyObject *name, PyObject *path_list) memory. */ found_encoding = PyTokenizer_FindEncoding(fd); lseek(fd, 0, 0); /* Reset position */ - if (found_encoding == NULL && PyErr_Occurred()) + if (found_encoding == NULL && PyErr_Occurred()) { + Py_XDECREF(pathobj); return NULL; + } encoding = (found_encoding != NULL) ? found_encoding : (char*)PyUnicode_GetDefaultEncoding(); } - fob = PyFile_FromFd(fd, pathname, fdp->mode, -1, + fob = PyFile_FromFd(fd, NULL, fdp->mode, -1, (char*)encoding, NULL, NULL, 1); if (fob == NULL) { + Py_XDECREF(pathobj); close(fd); PyMem_FREE(found_encoding); return NULL; @@ -3552,7 +3526,10 @@ call_find_module(PyObject *name, PyObject *path_list) fob = Py_None; Py_INCREF(fob); } - pathobj = PyUnicode_DecodeFSDefault(pathname); + if (pathobj == NULL) { + Py_INCREF(Py_None); + pathobj = Py_None; + } ret = Py_BuildValue("NN(ssi)", fob, pathobj, fdp->suffix, fdp->mode, fdp->type); PyMem_FREE(found_encoding); -- cgit v1.2.1 From 8784da32ff0f704a48459abf452eba8345f0d053 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 14:53:28 -0400 Subject: Issue #3080: imp.new_module() uses Unicode --- Python/import.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 5dcbf17710..3237ddc84e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3787,10 +3787,10 @@ imp_load_package(PyObject *self, PyObject *args) static PyObject * imp_new_module(PyObject *self, PyObject *args) { - char *name; - if (!PyArg_ParseTuple(args, "s:new_module", &name)) + PyObject *name; + if (!PyArg_ParseTuple(args, "U:new_module", &name)) return NULL; - return PyModule_New(name); + return PyModule_NewObject(name); } static PyObject * -- cgit v1.2.1 From 24cf6f1d864c6c51a299ed32ba9e1fe8701a4b54 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 15:05:12 -0400 Subject: Fix imp.cache_from_source() if the directory name contains a dot If the directory name contains a dot but not the filename, don't strip at the dot. --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 3237ddc84e..e5cb627003 100644 --- a/Python/import.c +++ b/Python/import.c @@ -943,12 +943,12 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) Py_UNICODE_strcat(buf, CACHEDIR_UNICODE); i += Py_UNICODE_strlen(CACHEDIR_UNICODE) - 1; buf[i++] = sep; - buf[i++] = '\0'; + buf[i] = '\0'; /* Add the base filename, but remove the .py or .pyw extension, since the tag name must go before the extension. */ Py_UNICODE_strcat(buf, pathname + save); - pos = Py_UNICODE_strrchr(buf, '.'); + pos = Py_UNICODE_strrchr(buf + i, '.'); if (pos != NULL) *++pos = '\0'; Py_UNICODE_strcat(buf, PYC_TAG_UNICODE); -- cgit v1.2.1 From 0b5200ff91987d460004543f52dc7443f57a6b36 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 15:15:47 -0400 Subject: Issue #3080: Use repr() to format the module name on error --- Python/import.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e5cb627003..65944473cc 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1431,7 +1431,7 @@ load_source_module(PyObject *name, PyObject *pathname, FILE *fp) goto error; if (Py_VerboseFlag) PySys_FormatStderr("import %U # from %R\n", - name, pathname); + name, pathname); if (cpathname != NULL) { PyObject *ro = PySys_GetObject("dont_write_bytecode"); if (ro == NULL || !PyObject_IsTrue(ro)) @@ -1517,8 +1517,8 @@ load_package(PyObject *name, PyObject *pathname) if (m == NULL) return NULL; if (Py_VerboseFlag) - PySys_FormatStderr("import %U # directory %U\n", - name, pathname); + PySys_FormatStderr("import %U # directory %R\n", + name, pathname); file = get_sourcefile(pathname); if (file == NULL) return NULL; @@ -1875,7 +1875,7 @@ find_module_path_list(PyObject *fullname, PyObject *name, Py_DECREF(prefix); } PyErr_Format(PyExc_ImportError, - "No module named %U", name); + "No module named %R", name); return NULL; } @@ -2366,7 +2366,7 @@ load_module(PyObject *name, FILE *fp, PyObject *pathname, int type, PyObject *lo default: PyErr_Format(PyExc_ImportError, - "Don't know how to import %U (type code %d)", + "Don't know how to import %R (type code %d)", name, type); m = NULL; @@ -3251,7 +3251,7 @@ PyImport_ReloadModule(PyObject *m) return NULL; if (m != PyDict_GetItem(modules, nameobj)) { PyErr_Format(PyExc_ImportError, - "reload(): module %U not in sys.modules", + "reload(): module %R not in sys.modules", nameobj); Py_DECREF(nameobj); return NULL; @@ -3286,7 +3286,7 @@ PyImport_ReloadModule(PyObject *m) parent = PyDict_GetItem(modules, parentname); if (parent == NULL) { PyErr_Format(PyExc_ImportError, - "reload(): parent %U not in sys.modules", + "reload(): parent %R not in sys.modules", parentname); Py_DECREF(parentname); goto error; -- cgit v1.2.1 From 67a022a7f5cdf458fa1e76d7b5482fec1784890f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 14 Mar 2011 15:54:52 -0400 Subject: Issue #3080: Add PyImport_ImportModuleLevelObject() function Use it for the builtin __import__ function. --- Python/bltinmodule.c | 11 ++++------- Python/import.c | 32 ++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ca40cb07dc..3074e4cb63 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -155,17 +155,14 @@ builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"name", "globals", "locals", "fromlist", "level", 0}; - char *name; - PyObject *globals = NULL; - PyObject *locals = NULL; - PyObject *fromlist = NULL; + PyObject *name, *globals = NULL, *locals = NULL, *fromlist = NULL; int level = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|OOOi:__import__", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|OOOi:__import__", kwlist, &name, &globals, &locals, &fromlist, &level)) return NULL; - return PyImport_ImportModuleLevel(name, globals, locals, - fromlist, level); + return PyImport_ImportModuleLevelObject(name, globals, locals, + fromlist, level); } PyDoc_STRVAR(import_doc, diff --git a/Python/import.c b/Python/import.c index 65944473cc..7f9042ac01 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2753,25 +2753,37 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, } PyObject * -PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist, int level) +PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, + PyObject *locals, PyObject *fromlist, + int level) { - PyObject *nameobj, *result; - nameobj = PyUnicode_FromString(name); - if (nameobj == NULL) - return NULL; + PyObject *mod; _PyImport_AcquireLock(); - result = import_module_level(nameobj, globals, locals, fromlist, level); - Py_DECREF(nameobj); + mod = import_module_level(name, globals, locals, fromlist, level); if (_PyImport_ReleaseLock() < 0) { - Py_XDECREF(result); + Py_XDECREF(mod); PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); return NULL; } - return result; + return mod; +} + +PyObject * +PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, + PyObject *fromlist, int level) +{ + PyObject *nameobj, *mod; + nameobj = PyUnicode_FromString(name); + if (nameobj == NULL) + return NULL; + mod = PyImport_ImportModuleLevelObject(nameobj, globals, locals, + fromlist, level); + Py_DECREF(nameobj); + return mod; } + /* Return the package that an import is being performed in. If globals comes from the module foo.bar.bat (not itself a package), this returns the sys.modules entry for foo.bar. If globals is from a package's __init__.py, -- cgit v1.2.1 From 83ee336336ccdc6b1fcc97ce0f693409ecf4b60a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 04:28:55 +0100 Subject: Issue #3080: Fix case_ok() using case_bytes() Invert name and namelen arguments. --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 7f9042ac01..0194d89956 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2208,8 +2208,8 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) match = case_bytes( PyBytes_AS_STRING(filebytes), PyBytes_GET_SIZE(filebytes) + prefix_delta, - PyBytes_AS_STRING(namebytes), - PyBytes_GET_SIZE(namebytes)); + PyBytes_GET_SIZE(namebytes), + PyBytes_AS_STRING(namebytes)); Py_DECREF(filebytes); Py_DECREF(namebytes); return match; -- cgit v1.2.1 From f8715e031dd6628c290bfc9341b092063449a6f8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 04:58:29 +0100 Subject: Issue #3080: Fix call to case_ok() in find_init_module() --- Python/import.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 0194d89956..38960b165d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2237,8 +2237,8 @@ find_init_module(PyObject *directory) if (filename == NULL) return -1; if (_Py_stat(filename, &statbuf) == 0) { - /* 9=len("/__init__") */ - match = case_ok(filename, 9, initstr); + /* 3=len(".py") */ + match = case_ok(filename, -3, initstr); if (match < 0) { Py_DECREF(filename); return -1; @@ -2255,8 +2255,8 @@ find_init_module(PyObject *directory) if (filename == NULL) return -1; if (_Py_stat(filename, &statbuf) == 0) { - /* 9=len("/__init__") */ - match = case_ok(filename, 9, initstr); + /* 4=len(".pyc") */ + match = case_ok(filename, -4, initstr); if (match < 0) { Py_DECREF(filename); return -1; -- cgit v1.2.1 From 6d71d6018e93b53f8af5ed0d268a4c834a5cdda2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 22:37:17 +0100 Subject: Issue #3080: imp.load_module() accepts None for the module path imp.find_module() returns None as module path for builtin and frozen builtins. --- Python/import.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 38960b165d..abc3906719 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3744,17 +3744,22 @@ imp_load_source(PyObject *self, PyObject *args) static PyObject * imp_load_module(PyObject *self, PyObject *args) { - PyObject *name, *fob, *pathname, *ret; + PyObject *name, *fob, *pathname, *pathname_obj, *ret; char *suffix; /* Unused */ char *mode; int type; FILE *fp; - if (!PyArg_ParseTuple(args, "UOO&(ssi):load_module", - &name, &fob, - PyUnicode_FSDecoder, &pathname, - &suffix, &mode, &type)) + if (!PyArg_ParseTuple(args, "UOO(ssi):load_module", + &name, &fob, &pathname_obj, &suffix, &mode, &type)) return NULL; + if (pathname_obj != Py_None) { + if (!PyUnicode_FSDecoder(pathname_obj, &pathname)) + return NULL; + } + else + pathname = NULL; + if (*mode) { /* Mode must start with 'r' or 'U' and must not contain '+'. Implicit in this test is the assumption that the mode @@ -3763,7 +3768,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); - Py_DECREF(pathname); + Py_XDECREF(pathname); return NULL; } } @@ -3772,12 +3777,12 @@ imp_load_module(PyObject *self, PyObject *args) else { fp = get_file(NULL, fob, mode); if (fp == NULL) { - Py_DECREF(pathname); + Py_XDECREF(pathname); return NULL; } } ret = load_module(name, fp, pathname, type, NULL); - Py_DECREF(pathname); + Py_XDECREF(pathname); if (fp) fclose(fp); return ret; -- cgit v1.2.1 From 8c709c419d16486b76126195864ed9376e8b849b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Mar 2011 23:09:03 +0100 Subject: Fix #11586: typo in initfsencoding() Patch written by Ray Allen. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 8e97d7fc24..38b2ab84fb 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -147,7 +147,7 @@ get_codec_name(const char *encoding) goto error; name_utf8 = _PyUnicode_AsString(name); - if (name == NULL) + if (name_utf8 == NULL) goto error; name_str = strdup(name_utf8); Py_DECREF(name); -- cgit v1.2.1 From 537925e7a1a167720d29146e27275efae5b2f69d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Mar 2011 18:15:42 +0100 Subject: Issue #10833: Use PyErr_Format() and PyUnicode_FromFormat() instead of PyOS_snprintf() to avoid temporary buffer allocated on the stack and a conversion from bytes to Unicode. --- Python/getargs.c | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index e1cef0cc58..4b57153b88 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -310,20 +310,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) if (max == 0) { if (args == NULL) return 1; - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes no arguments", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - PyErr_SetString(PyExc_TypeError, msgbuf); + PyErr_Format(PyExc_TypeError, + "%.200s%s takes no arguments", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); return 0; } else if (min == 1 && max == 1) { if (args == NULL) { - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes at least one argument", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - PyErr_SetString(PyExc_TypeError, msgbuf); + PyErr_Format(PyExc_TypeError, + "%.200s%s takes at least one argument", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); return 0; } msg = convertitem(args, &format, p_va, flags, levels, @@ -349,20 +347,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) len = PyTuple_GET_SIZE(args); if (len < min || max < len) { - if (message == NULL) { - PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.150s%s takes %s %d argument%s " - "(%ld given)", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()", - min==max ? "exactly" - : len < min ? "at least" : "at most", - len < min ? min : max, - (len < min ? min : max) == 1 ? "" : "s", - Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); - message = msgbuf; - } - PyErr_SetString(PyExc_TypeError, message); + if (message == NULL) + PyErr_Format(PyExc_TypeError, + "%.150s%s takes %s %d argument%s (%ld given)", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()", + min==max ? "exactly" + : len < min ? "at least" : "at most", + len < min ? min : max, + (len < min ? min : max) == 1 ? "" : "s", + Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); + else + PyErr_SetString(PyExc_TypeError, message); return 0; } @@ -1458,8 +1454,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, nargs = PyTuple_GET_SIZE(args); nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); if (nargs + nkeywords > len) { - PyErr_Format(PyExc_TypeError, "%s%s takes at most %d " - "argument%s (%d given)", + PyErr_Format(PyExc_TypeError, + "%s%s takes at most %d argument%s (%d given)", (fname == NULL) ? "function" : fname, (fname == NULL) ? "" : "()", len, -- cgit v1.2.1 From e4d2501d8d2d2050dd6950aa4a794003fb2c7889 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Mar 2011 01:09:21 +0100 Subject: Issue #7330, #10833: Replace %100s by %.100s and %200s by %.200s I suppose that the author would like to truncate the type name, not get a string of 100/200 characters. --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index d2444aa9f0..50d5aacd9e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4130,7 +4130,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) if (PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Format(PyExc_TypeError, "%.200s%.200s argument after * " - "must be a sequence, not %200s", + "must be a sequence, not %.200s", PyEval_GetFuncName(func), PyEval_GetFuncDesc(func), stararg->ob_type->tp_name); -- cgit v1.2.1 From 05292378fc049f9a5ffa9480d0ad27b25f2c5528 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Mar 2011 01:22:27 +0100 Subject: Issue #3080: On DJGPP, case_bytes() returns -1 to signal an error if the file cannot be found. --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index abc3906719..3b8ce931d9 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2084,7 +2084,7 @@ case_bytes(char *buf, Py_ssize_t len, Py_ssize_t namelen, const char *name) PyErr_Format(PyExc_NameError, "Can't find file for module %.100s\n(filename %.300s)", name, buf); - return 0; + return -1; } return strncmp(ffblk.ff_name, name, namelen) == 0; -- cgit v1.2.1 From aad56d7f47263bddcaca2765d03df11d81bc0926 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Mar 2011 10:46:35 +0100 Subject: Issue #11630, issue #3080: Fix refleak introduced by ef2b6305d395 --- Python/import.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 3b8ce931d9..907ccd797c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3705,12 +3705,15 @@ imp_load_dynamic(PyObject *self, PyObject *args) return NULL; if (fob != NULL) { fp = get_file(NULL, fob, "r"); - if (fp == NULL) + if (fp == NULL) { + Py_DECREF(pathname); return NULL; + } } else fp = NULL; mod = _PyImport_LoadDynamicModule(name, pathname, fp); + Py_DECREF(pathname); if (fp) fclose(fp); return mod; -- cgit v1.2.1 From 07853354ede24bc0033485b335e0859b8212a429 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Wed, 23 Mar 2011 17:59:37 +0000 Subject: Issue #11244: Remove outdated peepholer check that was preventing the peepholer from folding -0 and -0.0. Thanks Eugene Toder for the patch. --- Python/peephole.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 4bc65dcc31..69f61617f8 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -238,7 +238,7 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **ob static int fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v) { - PyObject *newconst=NULL/*, *v*/; + PyObject *newconst; Py_ssize_t len_consts; int opcode; @@ -250,9 +250,7 @@ fold_unaryops_on_constants(unsigned char *codestr, PyObject *consts, PyObject *v opcode = codestr[3]; switch (opcode) { case UNARY_NEGATIVE: - /* Preserve the sign of -0.0 */ - if (PyObject_IsTrue(v) == 1) - newconst = PyNumber_Negative(v); + newconst = PyNumber_Negative(v); break; case UNARY_INVERT: newconst = PyNumber_Invert(v); -- cgit v1.2.1 From 725c21b3a4aec4426ccaa4c0425ee4e777a9eb35 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 23 Mar 2011 16:14:42 -0700 Subject: Make importlib compatible with __import__ by "fixing" code.co_filename paths. __import__ does a little trick when importing from bytecode by back-patching the co_filename paths to point to the file location where the code object was loaded from, *not* where the code object was originally created. This allows co_filename to point to a valid path. Problem is that co_filename is immutable from Python, so a private function -- imp._fix_co_filename() -- had to be introduced in order to get things working properly. Originally the plan was to add a file argument to marshal.loads(), but that failed as the algorithm used by __import__ is not fully recursive as one might expect, so to be fully backwards-compatible the code used by __import__ needed to be exposed. This closes issue #6811 by taking a different approach than outlined in the issue. --- Python/import.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 907ccd797c..b074b834e9 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1374,6 +1374,32 @@ update_compiled_module(PyCodeObject *co, PyObject *newname) Py_DECREF(oldname); } +static PyObject * +imp_fix_co_filename(PyObject *self, PyObject *args) +{ + PyObject *co; + PyObject *file_path; + + if (!PyArg_ParseTuple(args, "OO:_fix_co_filename", &co, &file_path)) + return NULL; + + if (!PyCode_Check(co)) { + PyErr_SetString(PyExc_TypeError, + "first argument must be a code object"); + return NULL; + } + + if (!PyUnicode_Check(file_path)) { + PyErr_SetString(PyExc_TypeError, + "second argument must be a string"); + return NULL; + } + + update_compiled_module((PyCodeObject*)co, file_path); + + 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. */ @@ -3976,6 +4002,7 @@ static PyMethodDef imp_methods[] = { #endif {"load_package", imp_load_package, METH_VARARGS}, {"load_source", imp_load_source, METH_VARARGS}, + {"_fix_co_filename", imp_fix_co_filename, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; -- cgit v1.2.1 From b877636c2dfc63692a7649584cfc9fcf72ba2dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Araujo?= Date: Sat, 26 Mar 2011 01:55:15 +0100 Subject: Remove traces of division_warning left over from Python 2 (#10998) --- Python/sysmodule.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 31c6939068..33255ad72e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1312,7 +1312,6 @@ static PyTypeObject FlagsType; static PyStructSequence_Field flags_fields[] = { {"debug", "-d"}, - {"division_warning", "-Q"}, {"inspect", "-i"}, {"interactive", "-i"}, {"optimize", "-O or -OO"}, @@ -1336,9 +1335,9 @@ static PyStructSequence_Desc flags_desc = { flags__doc__, /* doc */ flags_fields, /* fields */ #ifdef RISCOS - 13 -#else 12 +#else + 11 #endif }; @@ -1356,7 +1355,6 @@ make_flags(void) PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag)) SetFlag(Py_DebugFlag); - SetFlag(Py_DivisionWarningFlag); SetFlag(Py_InspectFlag); SetFlag(Py_InteractiveFlag); SetFlag(Py_OptimizeFlag); -- cgit v1.2.1 From d3c216b4c8eb33b04cff0f81e2233fb2d662df64 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 31 Mar 2011 01:31:06 +0200 Subject: Issue #11393: Add the new faulthandler module --- Python/pythonrun.c | 21 +++++ Python/traceback.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 38b2ab84fb..f787a4f8b3 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -70,6 +70,8 @@ extern void _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); extern int _PyLong_Init(void); extern void PyLong_Fini(void); +extern int _PyFaulthandler_Init(void); +extern void _PyFaulthandler_Fini(void); #ifdef WITH_THREAD extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); @@ -286,6 +288,10 @@ Py_InitializeEx(int install_sigs) _PyImportHooks_Init(); + /* initialize the faulthandler module */ + if (_PyFaulthandler_Init()) + Py_FatalError("Py_Initialize: can't initialize faulthandler"); + /* Initialize _warnings. */ _PyWarnings_Init(); @@ -454,6 +460,9 @@ Py_Finalize(void) /* Destroy the database used by _PyImport_{Fixup,Find}Extension */ _PyImport_Fini(); + /* unload faulthandler module */ + _PyFaulthandler_Fini(); + /* Debugging stuff */ #ifdef COUNT_ALLOCS dump_counts(stdout); @@ -2100,11 +2109,23 @@ cleanup: void Py_FatalError(const char *msg) { + const int fd = fileno(stderr); + PyThreadState *tstate; + fprintf(stderr, "Fatal Python error: %s\n", msg); fflush(stderr); /* it helps in Windows debug build */ if (PyErr_Occurred()) { PyErr_PrintEx(0); } + else { + tstate = _Py_atomic_load_relaxed(&_PyThreadState_Current); + if (tstate != NULL) { + fputc('\n', stderr); + fflush(stderr); + _Py_DumpTraceback(fd, tstate); + } + } + #ifdef MS_WINDOWS { size_t len = strlen(msg); diff --git a/Python/traceback.c b/Python/traceback.c index 59bb3f0d15..37673d93e0 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -13,6 +13,11 @@ #define OFF(x) offsetof(PyTracebackObject, x) +#define PUTS(fd, str) write(fd, str, strlen(str)) +#define MAX_STRING_LENGTH 100 +#define MAX_FRAME_DEPTH 100 +#define MAX_NTHREADS 100 + /* Method from Parser/tokenizer.c */ extern char * PyTokenizer_FindEncoding(int); @@ -402,3 +407,233 @@ PyTraceBack_Print(PyObject *v, PyObject *f) err = tb_printinternal((PyTracebackObject *)v, f, limit); return err; } + +/* Reverse a string. For example, "abcd" becomes "dcba". + + This function is signal safe. */ + +static void +reverse_string(char *text, const size_t len) +{ + char tmp; + size_t i, j; + if (len == 0) + return; + for (i=0, j=len-1; i < j; i++, j--) { + tmp = text[i]; + text[i] = text[j]; + text[j] = tmp; + } +} + +/* Format an integer in range [0; 999999] to decimal, + and write it into the file fd. + + This function is signal safe. */ + +static void +dump_decimal(int fd, int value) +{ + char buffer[7]; + int len; + if (value < 0 || 999999 < value) + return; + len = 0; + do { + buffer[len] = '0' + (value % 10); + value /= 10; + len++; + } while (value); + reverse_string(buffer, len); + write(fd, buffer, len); +} + +/* Format an integer in range [0; 0xffffffff] to hexdecimal of 'width' digits, + and write it into the file fd. + + This function is signal safe. */ + +static void +dump_hexadecimal(int width, unsigned long value, int fd) +{ + const char *hexdigits = "0123456789abcdef"; + int len; + char buffer[sizeof(unsigned long) * 2 + 1]; + len = 0; + do { + buffer[len] = hexdigits[value & 15]; + value >>= 4; + len++; + } while (len < width || value); + reverse_string(buffer, len); + write(fd, buffer, len); +} + +/* Write an unicode object into the file fd using ascii+backslashreplace. + + This function is signal safe. */ + +static void +dump_ascii(int fd, PyObject *text) +{ + Py_ssize_t i, size; + int truncated; + Py_UNICODE *u; + char c; + + size = PyUnicode_GET_SIZE(text); + u = PyUnicode_AS_UNICODE(text); + + if (MAX_STRING_LENGTH < size) { + size = MAX_STRING_LENGTH; + truncated = 1; + } + else + truncated = 0; + + for (i=0; i < size; i++, u++) { + if (*u < 128) { + c = (char)*u; + write(fd, &c, 1); + } + else if (*u < 256) { + PUTS(fd, "\\x"); + dump_hexadecimal(2, *u, fd); + } + else +#ifdef Py_UNICODE_WIDE + if (*u < 65536) +#endif + { + PUTS(fd, "\\u"); + dump_hexadecimal(4, *u, fd); +#ifdef Py_UNICODE_WIDE + } + else { + PUTS(fd, "\\U"); + dump_hexadecimal(8, *u, fd); +#endif + } + } + if (truncated) + PUTS(fd, "..."); +} + +/* Write a frame into the file fd: "File "xxx", line xxx in xxx". + + This function is signal safe. */ + +static void +dump_frame(int fd, PyFrameObject *frame) +{ + PyCodeObject *code; + int lineno; + + code = frame->f_code; + PUTS(fd, " File "); + if (code != NULL && code->co_filename != NULL + && PyUnicode_Check(code->co_filename)) + { + write(fd, "\"", 1); + dump_ascii(fd, code->co_filename); + write(fd, "\"", 1); + } else { + PUTS(fd, "???"); + } + + /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ + lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti); + PUTS(fd, ", line "); + dump_decimal(fd, lineno); + PUTS(fd, " in "); + + if (code != NULL && code->co_name != NULL + && PyUnicode_Check(code->co_name)) + dump_ascii(fd, code->co_name); + else + PUTS(fd, "???"); + + write(fd, "\n", 1); +} + +static int +dump_traceback(int fd, PyThreadState *tstate, int write_header) +{ + PyFrameObject *frame; + unsigned int depth; + + frame = _PyThreadState_GetFrame(tstate); + if (frame == NULL) + return -1; + + if (write_header) + PUTS(fd, "Traceback (most recent call first):\n"); + depth = 0; + while (frame != NULL) { + if (MAX_FRAME_DEPTH <= depth) { + PUTS(fd, " ...\n"); + break; + } + if (!PyFrame_Check(frame)) + break; + dump_frame(fd, frame); + frame = frame->f_back; + depth++; + } + return 0; +} + +int +_Py_DumpTraceback(int fd, PyThreadState *tstate) +{ + return dump_traceback(fd, tstate, 1); +} + +/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if + is_current is true, "Thread 0xHHHH:\n" otherwise. + + This function is signal safe. */ + +static void +write_thread_id(int fd, PyThreadState *tstate, int is_current) +{ + if (is_current) + PUTS(fd, "Current thread 0x"); + else + PUTS(fd, "Thread 0x"); + dump_hexadecimal(sizeof(long)*2, (unsigned long)tstate->thread_id, fd); + PUTS(fd, ":\n"); +} + +const char* +_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, + PyThreadState *current_thread) +{ + PyThreadState *tstate; + unsigned int nthreads; + + /* Get the current interpreter from the current thread */ + tstate = PyInterpreterState_ThreadHead(interp); + if (tstate == NULL) + return "unable to get the thread head state"; + + /* Dump the traceback of each thread */ + tstate = PyInterpreterState_ThreadHead(interp); + nthreads = 0; + do + { + if (nthreads != 0) + write(fd, "\n", 1); + if (nthreads >= MAX_NTHREADS) { + PUTS(fd, "...\n"); + break; + } + write_thread_id(fd, tstate, tstate == current_thread); + dump_traceback(fd, tstate, 0); + tstate = PyThreadState_Next(tstate); + nthreads++; + } while (tstate != NULL); + + return NULL; +} + -- cgit v1.2.1 From eb92e63267528242069ef100470afec9147700ab Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 1 Apr 2011 12:13:55 +0200 Subject: Issue #11393: The fault handler handles also SIGABRT --- Python/pythonrun.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index f787a4f8b3..1c36e63ac4 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2124,6 +2124,7 @@ Py_FatalError(const char *msg) fflush(stderr); _Py_DumpTraceback(fd, tstate); } + _PyFaulthandler_Fini(); } #ifdef MS_WINDOWS -- cgit v1.2.1 From 28169f0c91398cc93c3c5d114f055ab1e3ecbd59 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 1 Apr 2011 15:34:01 +0200 Subject: Issue #11393: _Py_DumpTraceback() writes the header even if there is no frame --- Python/traceback.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/traceback.c b/Python/traceback.c index 37673d93e0..f0142da792 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -556,18 +556,19 @@ dump_frame(int fd, PyFrameObject *frame) write(fd, "\n", 1); } -static int +static void dump_traceback(int fd, PyThreadState *tstate, int write_header) { PyFrameObject *frame; unsigned int depth; + if (write_header) + PUTS(fd, "Traceback (most recent call first):\n"); + frame = _PyThreadState_GetFrame(tstate); if (frame == NULL) - return -1; + return; - if (write_header) - PUTS(fd, "Traceback (most recent call first):\n"); depth = 0; while (frame != NULL) { if (MAX_FRAME_DEPTH <= depth) { @@ -580,13 +581,12 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header) frame = frame->f_back; depth++; } - return 0; } -int +void _Py_DumpTraceback(int fd, PyThreadState *tstate) { - return dump_traceback(fd, tstate, 1); + dump_traceback(fd, tstate, 1); } /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if -- cgit v1.2.1 From d206f91d5300b6ee4d99d9d45f9a4160fa384366 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 4 Apr 2011 23:05:53 +0200 Subject: Issue #11619: _PyImport_LoadDynamicModule() doesn't encode the path to bytes on Windows. --- Python/dynload_win.c | 33 ++++++++++++++++----------------- Python/importdl.c | 11 +++++++++++ 2 files changed, 27 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 9c04250f33..9869f6ae8b 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -171,8 +171,8 @@ static char *GetPythonImport (HINSTANCE hModule) return NULL; } -dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, - const char *pathname, FILE *fp) +dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, + PyObject *pathname, FILE *fp) { dl_funcptr p; char funcname[258], *import_python; @@ -185,8 +185,7 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, { HINSTANCE hDLL = NULL; - char pathbuf[260]; - LPTSTR dummy; + wchar_t pathbuf[260]; unsigned int old_mode; ULONG_PTR cookie = 0; /* We use LoadLibraryEx so Windows looks for dependent DLLs @@ -198,14 +197,14 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, /* Don't display a message box when Python can't load a DLL */ old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - if (GetFullPathName(pathname, - sizeof(pathbuf), - pathbuf, - &dummy)) { + if (GetFullPathNameW(PyUnicode_AS_UNICODE(pathname), + sizeof(pathbuf) / sizeof(pathbuf[0]), + pathbuf, + NULL)) { ULONG_PTR cookie = _Py_ActivateActCtx(); /* XXX This call doesn't exist in Windows CE */ - hDLL = LoadLibraryEx(pathname, NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); + hDLL = LoadLibraryExW(PyUnicode_AS_UNICODE(pathname), NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); _Py_DeactivateActCtx(cookie); } @@ -264,21 +263,21 @@ dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, } else { char buffer[256]; + PyOS_snprintf(buffer, sizeof(buffer), #ifdef _DEBUG - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d_d.dll", + "python%d%d_d.dll", #else - PyOS_snprintf(buffer, sizeof(buffer), "python%d%d.dll", + "python%d%d.dll", #endif PY_MAJOR_VERSION,PY_MINOR_VERSION); import_python = GetPythonImport(hDLL); if (import_python && strcasecmp(buffer,import_python)) { - PyOS_snprintf(buffer, sizeof(buffer), - "Module use of %.150s conflicts " - "with this version of Python.", - import_python); - PyErr_SetString(PyExc_ImportError,buffer); + PyErr_Format(PyExc_ImportError, + "Module use of %.150s conflicts " + "with this version of Python.", + import_python); FreeLibrary(hDLL); return NULL; } diff --git a/Python/importdl.c b/Python/importdl.c index 629f3e294e..69bb7117ad 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -12,8 +12,13 @@ #include "importdl.h" +#ifdef MS_WINDOWS +extern dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, + PyObject *pathname, FILE *fp); +#else extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp); +#endif /* name should be ASCII only because the C language doesn't accept non-ASCII identifiers, and dynamic modules are written in C. */ @@ -22,7 +27,9 @@ PyObject * _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) { PyObject *m; +#ifndef MS_WINDOWS PyObject *pathbytes; +#endif char *namestr, *lastdot, *shortname, *packagecontext, *oldcontext; dl_funcptr p0; PyObject* (*p)(void); @@ -48,12 +55,16 @@ _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) shortname = lastdot+1; } +#ifdef MS_WINDOWS + p0 = _PyImport_GetDynLoadWindows(shortname, path, fp); +#else pathbytes = PyUnicode_EncodeFSDefault(path); if (pathbytes == NULL) return NULL; p0 = _PyImport_GetDynLoadFunc(shortname, PyBytes_AS_STRING(pathbytes), fp); Py_DECREF(pathbytes); +#endif p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) return NULL; -- cgit v1.2.1 From 8136044f569744c1f5fbb37a093e2728db859ee0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 5 Apr 2011 00:39:01 +0200 Subject: Issue #10785: Store the filename as Unicode in the Python parser. --- Python/pythonrun.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1c36e63ac4..a6787c4fc7 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -62,6 +62,7 @@ static PyObject *run_mod(mod_ty, const char *, PyObject *, PyObject *, static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *, PyCompilerFlags *); static void err_input(perrdetail *); +static void err_free(perrdetail *); static void initsigs(void); static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); @@ -1887,12 +1888,13 @@ PyParser_ASTFromString(const char *s, const char *filename, int start, flags->cf_flags |= iflags & PyCF_MASK; mod = PyAST_FromNode(n, flags, filename, arena); PyNode_Free(n); - return mod; } else { err_input(&err); - return NULL; + mod = NULL; } + err_free(&err); + return mod; } mod_ty @@ -1917,14 +1919,15 @@ PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc, flags->cf_flags |= iflags & PyCF_MASK; mod = PyAST_FromNode(n, flags, filename, arena); PyNode_Free(n); - return mod; } else { err_input(&err); if (errcode) *errcode = err.error; - return NULL; + mod = NULL; } + err_free(&err); + return mod; } /* Simplified interface to parsefile -- return node or set exception */ @@ -1938,6 +1941,7 @@ PyParser_SimpleParseFileFlags(FILE *fp, const char *filename, int start, int fla start, NULL, NULL, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1952,6 +1956,7 @@ PyParser_SimpleParseStringFlags(const char *str, int start, int flags) start, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1964,6 +1969,7 @@ PyParser_SimpleParseStringFlagsFilename(const char *str, const char *filename, &_PyParser_Grammar, start, &err, flags); if (n == NULL) err_input(&err); + err_free(&err); return n; } @@ -1976,12 +1982,24 @@ PyParser_SimpleParseStringFilename(const char *str, const char *filename, int st /* May want to move a more generalized form of this to parsetok.c or even parser modules. */ +void +PyParser_ClearError(perrdetail *err) +{ + err_free(err); +} + void PyParser_SetError(perrdetail *err) { err_input(err); } +static void +err_free(perrdetail *err) +{ + Py_CLEAR(err->filename); +} + /* Set the error appropriate to the given input error code (see errcode.h) */ static void @@ -1989,7 +2007,6 @@ err_input(perrdetail *err) { PyObject *v, *w, *errtype, *errtext; PyObject *msg_obj = NULL; - PyObject *filename; char *msg = NULL; errtype = PyExc_SyntaxError; @@ -2075,17 +2092,8 @@ err_input(perrdetail *err) errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text), "replace"); } - if (err->filename != NULL) - filename = PyUnicode_DecodeFSDefault(err->filename); - else { - Py_INCREF(Py_None); - filename = Py_None; - } - if (filename != NULL) - v = Py_BuildValue("(NiiN)", filename, - err->lineno, err->offset, errtext); - else - v = NULL; + v = Py_BuildValue("(OiiN)", err->filename, + err->lineno, err->offset, errtext); if (v != NULL) { if (msg_obj) w = Py_BuildValue("(OO)", msg_obj, v); -- cgit v1.2.1 From f41c2fdbb05ad29ad7c2a6a65dfac2e9d919f022 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 5 Apr 2011 01:48:03 +0200 Subject: Issue #9319: Include the filename in "Non-UTF8 code ..." syntax error. --- Python/import.c | 10 +++++----- Python/traceback.c | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b074b834e9..4159a8ece6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -124,12 +124,12 @@ static const Py_UNICODE PYC_TAG_UNICODE[] = { /* See _PyImport_FixupExtensionObject() below */ static PyObject *extensions = NULL; +/* Function from Parser/tokenizer.c */ +extern char * PyTokenizer_FindEncodingFilename(int, PyObject *); + /* This table is defined in config.c: */ extern struct _inittab _PyImport_Inittab[]; -/* Method from Parser/tokenizer.c */ -extern char * PyTokenizer_FindEncoding(int); - struct _inittab *PyImport_Inittab = _PyImport_Inittab; /* these tables define the module suffixes that Python recognizes */ @@ -3540,9 +3540,9 @@ call_find_module(PyObject *name, PyObject *path_list) } if (fd != -1) { if (strchr(fdp->mode, 'b') == NULL) { - /* PyTokenizer_FindEncoding() returns PyMem_MALLOC'ed + /* PyTokenizer_FindEncodingFilename() returns PyMem_MALLOC'ed memory. */ - found_encoding = PyTokenizer_FindEncoding(fd); + found_encoding = PyTokenizer_FindEncodingFilename(fd, pathobj); lseek(fd, 0, 0); /* Reset position */ if (found_encoding == NULL && PyErr_Occurred()) { Py_XDECREF(pathobj); diff --git a/Python/traceback.c b/Python/traceback.c index f0142da792..e74a1474df 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -18,8 +18,8 @@ #define MAX_FRAME_DEPTH 100 #define MAX_NTHREADS 100 -/* Method from Parser/tokenizer.c */ -extern char * PyTokenizer_FindEncoding(int); +/* Function from Parser/tokenizer.c */ +extern char * PyTokenizer_FindEncodingFilename(int, PyObject *); static PyObject * tb_dir(PyTracebackObject *self) @@ -251,7 +251,7 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) /* use the right encoding to decode the file as unicode */ fd = PyObject_AsFileDescriptor(binary); - found_encoding = PyTokenizer_FindEncoding(fd); + found_encoding = PyTokenizer_FindEncodingFilename(fd, filename); encoding = (found_encoding != NULL) ? found_encoding : "utf-8"; lseek(fd, 0, 0); /* Reset position */ fob = PyObject_CallMethod(io, "TextIOWrapper", "Os", binary, encoding); -- cgit v1.2.1 From ae969fff7c82badeba0cfd4e9f4f78841d9df38e Mon Sep 17 00:00:00 2001 From: Eli Bendersky Date: Sun, 10 Apr 2011 07:37:26 +0300 Subject: Issue #9904: fix and clarify some comments + fix indentation in symtable code --- Python/symtable.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 15ba6b5e2f..8040665b58 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -750,7 +750,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, goto error; } - /* Recursively call analyze_block() on each child block. + /* Recursively call analyze_child_block() on each child block. newbound, newglobal now contain the names visible in nested blocks. The free variables in the children will @@ -1205,9 +1205,9 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) case Raise_kind: if (s->v.Raise.exc) { VISIT(st, expr, s->v.Raise.exc); - if (s->v.Raise.cause) { - VISIT(st, expr, s->v.Raise.cause); - } + if (s->v.Raise.cause) { + VISIT(st, expr, s->v.Raise.cause); + } } break; case TryExcept_kind: -- cgit v1.2.1 From 87c4bc18d9591c89d76f68cbd67960d2a1309075 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 19 Apr 2011 23:58:51 +0200 Subject: Issue #11223: Add threading._info() function providing informations about the thread implementation. Skip test_lock_acquire_interruption() and test_rlock_acquire_interruption() of test_threadsignals if a thread lock is implemented using a POSIX mutex and a POSIX condition variable. A POSIX condition variable cannot be interrupted by a signal (e.g. on Linux, the futex system call is restarted). --- Python/thread.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index d224046e64..5213a725ae 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -100,6 +100,7 @@ static size_t _pythread_stacksize = 0; #endif #ifdef SOLARIS_THREADS +#define PYTHREAD_NAME "solaris" #include "thread_solaris.h" #endif @@ -115,6 +116,7 @@ static size_t _pythread_stacksize = 0; #endif #ifdef _POSIX_THREADS +#define PYTHREAD_NAME "pthread" #include "thread_pthread.h" #endif @@ -124,14 +126,17 @@ static size_t _pythread_stacksize = 0; #endif #ifdef NT_THREADS +#define PYTHREAD_NAME "nt" #include "thread_nt.h" #endif #ifdef OS2_THREADS +#define PYTHREAD_NAME "os2" #include "thread_os2.h" #endif #ifdef PLAN9_THREADS +#define PYTHREAD_NAME "plan9" #include "thread_plan9.h" #endif @@ -409,3 +414,55 @@ PyThread_ReInitTLS(void) } #endif /* Py_HAVE_NATIVE_TLS */ + +PyObject* +_PyThread_Info(void) +{ + PyObject *info, *value; + int ret; + char buffer[255]; + int len; + + info = PyDict_New(); + if (info == NULL) + return NULL; + + value = PyUnicode_FromString(PYTHREAD_NAME); + ret = PyDict_SetItemString(info, "name", value); + Py_DECREF(value); + if (ret) + goto error; + +#ifdef _POSIX_THREADS +#ifdef USE_SEMAPHORES + value = PyUnicode_FromString("semaphore"); +#else + value = PyUnicode_FromString("mutex+cond"); +#endif + if (value == NULL) + return NULL; + ret = PyDict_SetItemString(info, "lock_implementation", value); + Py_DECREF(value); + if (ret) + goto error; + +#if defined(HAVE_CONFSTR) && defined(_CS_GNU_LIBPTHREAD_VERSION) + len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); + if (0 < len && len < sizeof(buffer)) { + value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); + if (value == NULL) + goto error; + ret = PyDict_SetItemString(info, "pthread_version", value); + Py_DECREF(value); + if (ret) + goto error; + } +#endif +#endif + + return info; + +error: + Py_DECREF(info); + return NULL; +} -- cgit v1.2.1 From 0cd7388f789c312864700c151157a939f07cc090 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Apr 2011 03:27:51 +0200 Subject: Close #11619: write_compiled_module() doesn't encode the filename Reimplement open_exclusive() using _wopen() to avoid encoding the filename to the filesystem encoding: use the Unicode version of the Windows API. --- Python/import.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 4159a8ece6..5360d57c51 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1198,6 +1198,7 @@ parse_source_module(PyObject *pathname, FILE *fp) /* Helper to open a bytecode file for writing in exclusive mode */ +#ifndef MS_WINDOWS static FILE * open_exclusive(char *filename, mode_t mode) { @@ -1228,6 +1229,7 @@ open_exclusive(char *filename, mode_t mode) return fopen(filename, "wb"); #endif } +#endif /* Write a compiled module to a file, placing the time of last @@ -1250,7 +1252,12 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, S_IWUSR | S_IWGRP | S_IWOTH); PyObject *dirbytes; #endif - PyObject *cpathbytes, *dirname; +#ifdef MS_WINDOWS + int fd; +#else + PyObject *cpathbytes; +#endif + PyObject *dirname; Py_UNICODE *dirsep; int res, ok; @@ -1294,6 +1301,16 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } Py_DECREF(dirname); +#ifdef MS_WINDOWS + (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname)); + fd = _wopen(PyUnicode_AS_UNICODE(cpathname), + O_EXCL | O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, + mode); + if (0 <= fd) + fp = fdopen(fd, "wb"); + else + fp = NULL; +#else cpathbytes = PyUnicode_EncodeFSDefault(cpathname); if (cpathbytes == NULL) { PyErr_Clear(); @@ -1301,11 +1318,14 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } fp = open_exclusive(PyBytes_AS_STRING(cpathbytes), mode); +#endif if (fp == NULL) { if (Py_VerboseFlag) PySys_FormatStderr( "# can't create %R\n", cpathname); +#ifndef MS_WINDOWS Py_DECREF(cpathbytes); +#endif return; } PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); @@ -1321,11 +1341,13 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname)); #else (void) unlink(PyBytes_AS_STRING(cpathbytes)); -#endif Py_DECREF(cpathbytes); +#endif return; } +#ifndef MS_WINDOWS Py_DECREF(cpathbytes); +#endif /* Now write the true mtime */ fseek(fp, 4L, 0); assert(mtime < LONG_MAX); -- cgit v1.2.1 From 77029dd04748b0be6894feb404f7fae63c20bb5c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 20 Apr 2011 12:23:26 +0200 Subject: Issue #11223: fix compiler warnings --- Python/thread.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index 5213a725ae..1f15a22e2f 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -420,8 +420,11 @@ _PyThread_Info(void) { PyObject *info, *value; int ret; +#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ + && defined(_CS_GNU_LIBPTHREAD_VERSION)) char buffer[255]; int len; +#endif info = PyDict_New(); if (info == NULL) -- cgit v1.2.1 From db32b7ada2bd63927e2ecd2c32427baec6e44fda Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Apr 2011 00:20:27 +0200 Subject: Issue #10914: Py_NewInterpreter() uses PyErr_PrintEx(0) ... instead of PyErr_Print() because we don't need to set sys attributes, the sys module is destroyed just after printing the error. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a6787c4fc7..99bd66d7ad 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -632,7 +632,7 @@ Py_NewInterpreter(void) handle_error: /* Oops, it didn't work. Undo it all. */ - PyErr_Print(); + PyErr_PrintEx(0); PyThreadState_Clear(tstate); PyThreadState_Swap(save_tstate); PyThreadState_Delete(tstate); -- cgit v1.2.1 From 94efbe0ac4d55d812c49fa29accc75e135526975 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Apr 2011 00:24:21 +0200 Subject: Issue #10914: Initialize correctly the filesystem codec when creating a new subinterpreter to fix a bootstrap issue with codecs implemented in Python, as the ISO-8859-15 codec. Add fscodec_initialized attribute to the PyInterpreterState structure. --- Python/pystate.c | 1 + Python/pythonrun.c | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/pystate.c b/Python/pystate.c index 922e9a3780..65219eb6b6 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -79,6 +79,7 @@ PyInterpreterState_New(void) interp->codec_search_cache = NULL; interp->codec_error_registry = NULL; interp->codecs_initialized = 0; + interp->fscodec_initialized = 0; #ifdef HAVE_DLOPEN #ifdef RTLD_NOW interp->dlopenflags = RTLD_NOW; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 99bd66d7ad..ad31613651 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -53,7 +53,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ /* Forward */ static void initmain(void); -static void initfsencoding(void); +static int initfsencoding(PyInterpreterState *interp); static void initsite(void); static int initstdio(void); static void flush_io(void); @@ -298,7 +298,8 @@ Py_InitializeEx(int install_sigs) _PyTime_Init(); - initfsencoding(); + if (initfsencoding(interp) < 0) + Py_FatalError("Py_Initialize: unable to load the file system codec"); if (install_sigs) initsigs(); /* Signal handling stuff, including initintr() */ @@ -618,6 +619,10 @@ Py_NewInterpreter(void) Py_DECREF(pstderr); _PyImportHooks_Init(); + + if (initfsencoding(interp) < 0) + goto handle_error; + if (initstdio() < 0) Py_FatalError( "Py_Initialize: can't initialize sys standard streams"); @@ -730,8 +735,8 @@ initmain(void) } } -static void -initfsencoding(void) +static int +initfsencoding(PyInterpreterState *interp) { PyObject *codec; #if defined(HAVE_LANGINFO_H) && defined(CODESET) @@ -748,7 +753,8 @@ initfsencoding(void) Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; - return; + interp->fscodec_initialized = 1; + return 0; } #endif @@ -758,10 +764,11 @@ initfsencoding(void) /* Such error can only occurs in critical situations: no more * memory, import a module of the standard library failed, * etc. */ - Py_FatalError("Py_Initialize: unable to load the file system codec"); - } else { - Py_DECREF(codec); + return -1; } + Py_DECREF(codec); + interp->fscodec_initialized = 1; + return 0; } /* Import the site module (not into __main__ though) */ -- cgit v1.2.1 From da93e1034d0920de202f9ff0e941cc76dfc3e925 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 30 Apr 2011 14:53:09 +0200 Subject: Issue #11223: Replace threading._info() by sys.thread_info --- Python/sysmodule.c | 24 ++++++++++------ Python/thread.c | 83 +++++++++++++++++++++++++++++++++++------------------- 2 files changed, 69 insertions(+), 38 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index fdf361fa8b..b549203536 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -17,6 +17,7 @@ Data members: #include "Python.h" #include "code.h" #include "frameobject.h" +#include "pythread.h" #include "osdefs.h" @@ -1251,20 +1252,21 @@ PyDoc_STR( "\n\ Static objects:\n\ \n\ -float_info -- a dict with information about the float implementation.\n\ +builtin_module_names -- tuple of module names built into this interpreter\n\ +copyright -- copyright notice pertaining to this interpreter\n\ +exec_prefix -- prefix used to find the machine-specific Python library\n\ +executable -- pathname of this Python interpreter\n\ +float_info -- a struct sequence with information about the float implementation.\n\ +float_repr_style -- string indicating the style of repr() output for floats\n\ +hexversion -- version information encoded as a single integer\n\ int_info -- a struct sequence with information about the int implementation.\n\ maxsize -- the largest supported length of containers.\n\ maxunicode -- the largest supported character\n\ -builtin_module_names -- tuple of module names built into this interpreter\n\ -version -- the version of this interpreter as a string\n\ -version_info -- version information as a named tuple\n\ -hexversion -- version information encoded as a single integer\n\ -copyright -- copyright notice pertaining to this interpreter\n\ platform -- platform identifier\n\ -executable -- pathname of this Python interpreter\n\ prefix -- prefix used to find the Python library\n\ -exec_prefix -- prefix used to find the machine-specific Python library\n\ -float_repr_style -- string indicating the style of repr() output for floats\n\ +thread_info -- a struct sequence with information about the thread implementation.\n\ +version -- the version of this interpreter as a string\n\ +version_info -- version information as a named tuple\n\ " ) #ifdef MS_WINDOWS @@ -1611,6 +1613,10 @@ _PySys_Init(void) PyUnicode_FromString("legacy")); #endif +#ifdef WITH_THREAD + SET_SYS_FROM_STRING("thread_info", PyThread_GetInfo()); +#endif + #undef SET_SYS_FROM_STRING if (PyErr_Occurred()) return NULL; diff --git a/Python/thread.c b/Python/thread.c index 1f15a22e2f..c7d17d60e9 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -7,7 +7,6 @@ #include "Python.h" - #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro not present in unistd.h. But they still can be implemented as an external @@ -415,26 +414,51 @@ PyThread_ReInitTLS(void) #endif /* Py_HAVE_NATIVE_TLS */ +PyDoc_STRVAR(threadinfo__doc__, +"sys.thread_info\n\ +\n\ +A struct sequence holding information about the thread implementation."); + +static PyStructSequence_Field threadinfo_fields[] = { + {"name", "name of the thread implementation"}, + {"lock", "name of the lock implementation"}, + {"version", "name and version of the thread library"}, + {0} +}; + +static PyStructSequence_Desc threadinfo_desc = { + "sys.thread_info", /* name */ + threadinfo__doc__, /* doc */ + threadinfo_fields, /* fields */ + 3 +}; + +static PyTypeObject ThreadInfoType; + PyObject* -_PyThread_Info(void) +PyThread_GetInfo(void) { - PyObject *info, *value; - int ret; + PyObject *threadinfo, *value; + int pos = 0; #if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ && defined(_CS_GNU_LIBPTHREAD_VERSION)) char buffer[255]; int len; #endif - info = PyDict_New(); - if (info == NULL) + if (ThreadInfoType.tp_name == 0) + PyStructSequence_InitType(&ThreadInfoType, &threadinfo_desc); + + threadinfo = PyStructSequence_New(&ThreadInfoType); + if (threadinfo == NULL) return NULL; value = PyUnicode_FromString(PYTHREAD_NAME); - ret = PyDict_SetItemString(info, "name", value); - Py_DECREF(value); - if (ret) - goto error; + if (value == NULL) { + Py_DECREF(threadinfo); + return NULL; + } + PyStructSequence_SET_ITEM(threadinfo, pos++, value); #ifdef _POSIX_THREADS #ifdef USE_SEMAPHORES @@ -442,30 +466,31 @@ _PyThread_Info(void) #else value = PyUnicode_FromString("mutex+cond"); #endif - if (value == NULL) + if (value == NULL) { + Py_DECREF(threadinfo); return NULL; - ret = PyDict_SetItemString(info, "lock_implementation", value); - Py_DECREF(value); - if (ret) - goto error; + } +#else + Py_INCREF(Py_None); + value = Py_None; +#endif + PyStructSequence_SET_ITEM(threadinfo, pos++, value); -#if defined(HAVE_CONFSTR) && defined(_CS_GNU_LIBPTHREAD_VERSION) +#if (defined(_POSIX_THREADS) && defined(HAVE_CONFSTR) \ + && defined(_CS_GNU_LIBPTHREAD_VERSION)) + value = NULL; len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); - if (0 < len && len < sizeof(buffer)) { + if (1 < len && len < sizeof(buffer)) { value = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); if (value == NULL) - goto error; - ret = PyDict_SetItemString(info, "pthread_version", value); - Py_DECREF(value); - if (ret) - goto error; + PyErr_Clear(); } + if (value == NULL) #endif -#endif - - return info; - -error: - Py_DECREF(info); - return NULL; + { + Py_INCREF(Py_None); + value = Py_None; + } + PyStructSequence_SET_ITEM(threadinfo, pos++, value); + return threadinfo; } -- cgit v1.2.1 From ac8f9652916d3c88b8d08aaf32fa6942531cd712 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 7 May 2011 12:43:00 +0200 Subject: faulthandler: dump all threads by default * Set the default value of all_threads arguments to True * Py_FatalError() dumps all threads, instead of only the current thread Dump only the current thread is not reliable. In some cases, Python is unable to retrieve the state of the current thread and so is unable to dump the traceback. faulthandler keeps a reference to the interpreter and so is always able to dump the traceback of all threads. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index ebc4f1cf17..6ebc823b80 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2144,7 +2144,7 @@ Py_FatalError(const char *msg) if (tstate != NULL) { fputc('\n', stderr); fflush(stderr); - _Py_DumpTraceback(fd, tstate); + _Py_DumpTracebackThreads(fd, tstate->interp, tstate); } _PyFaulthandler_Fini(); } -- cgit v1.2.1 From 18375ee7ae1add544b3f1a13a9aa86e0748c20fb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 7 May 2011 12:46:05 +0200 Subject: _PyImport_LoadDynamicModule() encodes the module name explicitly to ASCII The name must be encodable to ASCII because dynamic module must have a function called "PyInit_NAME", they are written in C, and the C language doesn't accept non-ASCII identifiers. --- Python/importdl.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/importdl.c b/Python/importdl.c index 69bb7117ad..9127d61de3 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -20,31 +20,36 @@ extern dl_funcptr _PyImport_GetDynLoadFunc(const char *shortname, const char *pathname, FILE *fp); #endif -/* name should be ASCII only because the C language doesn't accept non-ASCII - identifiers, and dynamic modules are written in C. */ - PyObject * _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) { - PyObject *m; + PyObject *m = NULL; #ifndef MS_WINDOWS PyObject *pathbytes; #endif + PyObject *nameascii; char *namestr, *lastdot, *shortname, *packagecontext, *oldcontext; dl_funcptr p0; PyObject* (*p)(void); struct PyModuleDef *def; - namestr = _PyUnicode_AsString(name); - if (namestr == NULL) - return NULL; - m = _PyImport_FindExtensionObject(name, path); if (m != NULL) { Py_INCREF(m); return m; } + /* name must be encodable to ASCII because dynamic module must have a + function called "PyInit_NAME", they are written in C, and the C language + doesn't accept non-ASCII identifiers. */ + nameascii = PyUnicode_AsEncodedString(name, "ascii", NULL); + if (nameascii == NULL) + return NULL; + + namestr = PyBytes_AS_STRING(nameascii); + if (namestr == NULL) + goto error; + lastdot = strrchr(namestr, '.'); if (lastdot == NULL) { packagecontext = NULL; @@ -60,34 +65,33 @@ _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) #else pathbytes = PyUnicode_EncodeFSDefault(path); if (pathbytes == NULL) - return NULL; + goto error; p0 = _PyImport_GetDynLoadFunc(shortname, PyBytes_AS_STRING(pathbytes), fp); Py_DECREF(pathbytes); #endif p = (PyObject*(*)(void))p0; if (PyErr_Occurred()) - return NULL; + goto error; if (p == NULL) { PyErr_Format(PyExc_ImportError, "dynamic module does not define init function" " (PyInit_%s)", shortname); - return NULL; + goto error; } oldcontext = _Py_PackageContext; _Py_PackageContext = packagecontext; m = (*p)(); _Py_PackageContext = oldcontext; if (m == NULL) - return NULL; + goto error; if (PyErr_Occurred()) { - Py_DECREF(m); PyErr_Format(PyExc_SystemError, "initialization of %s raised unreported exception", shortname); - return NULL; + goto error; } /* Remember pointer to module init function. */ @@ -101,12 +105,18 @@ _PyImport_LoadDynamicModule(PyObject *name, PyObject *path, FILE *fp) Py_INCREF(path); if (_PyImport_FixupExtensionObject(m, name, path) < 0) - return NULL; + goto error; if (Py_VerboseFlag) PySys_FormatStderr( "import %U # dynamically loaded from %R\n", name, path); + Py_DECREF(nameascii); return m; + +error: + Py_DECREF(nameascii); + Py_XDECREF(m); + return NULL; } #endif /* HAVE_DYNAMIC_LOADING */ -- cgit v1.2.1 From bf30ea7ad386f8851207ea9d410a3215b03d31af Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 25 May 2011 09:29:00 -0500 Subject: make PyImport_ImportModuleLevel's first arg const like similiar functions (closes #12173) --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 5360d57c51..bfb976c77c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2818,7 +2818,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } PyObject * -PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, +PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { PyObject *nameobj, *mod; -- cgit v1.2.1 From 54ecf696bb489a653324f5b8a20018495b8f0142 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 26 May 2011 13:47:08 +0200 Subject: Remove useless assignments Warnings found by the the Clang Static Analyzer. --- Python/import.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index bfb976c77c..1f28d2233d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1733,7 +1733,6 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, Py_UNICODE buf[MAXPATHLEN+1]; Py_ssize_t buflen = MAXPATHLEN+1; PyObject *path_unicode, *filename; - const Py_UNICODE *base; Py_ssize_t len; struct stat statbuf; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; @@ -1751,7 +1750,6 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, else return 0; - base = PyUnicode_AS_UNICODE(path_unicode); len = PyUnicode_GET_SIZE(path_unicode); if (len + 2 + PyUnicode_GET_SIZE(name) + MAXSUFFIXSIZE >= buflen) { Py_DECREF(path_unicode); @@ -2275,12 +2273,10 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) static int find_init_module(PyObject *directory) { - size_t len; struct stat statbuf; PyObject *filename; int match; - len = PyUnicode_GET_SIZE(directory); filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); if (filename == NULL) return -1; -- cgit v1.2.1 From 9b94667b79d7b7152657519e1903cdcae790be88 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 26 May 2011 13:53:47 +0200 Subject: Avoid useless "++" at the end of functions Warnings found by the Clang Static Analyzer. --- Python/compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 53f5a12cc3..d195967e7c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3747,11 +3747,11 @@ assemble_lnotab(struct assembler *a, struct instr *i) a->a_lnotab_off += 2; if (d_bytecode) { *lnotab++ = d_bytecode; - *lnotab++ = d_lineno; + *lnotab = d_lineno; } else { /* First line of a block; def stmt, etc. */ *lnotab++ = 0; - *lnotab++ = d_lineno; + *lnotab = d_lineno; } a->a_lineno = i->i_lineno; a->a_lineno_off = a->a_offset; @@ -3796,7 +3796,7 @@ assemble_emit(struct assembler *a, struct instr *i) if (i->i_hasarg) { assert(size == 3 || size == 6); *code++ = arg & 0xff; - *code++ = arg >> 8; + *code = arg >> 8; } return 1; } -- cgit v1.2.1 From 48f7ac826a35230300859e8bfba3b7339efab679 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 26 May 2011 14:25:13 +0200 Subject: print_exception(): handle correctly PyObject_GetAttrString() failure Bug found by the Clang Static Analyzer. --- Python/pythonrun.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index b55dc5b201..232d7befa0 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1593,7 +1593,7 @@ print_exception(PyObject *f, PyObject *value) moduleName = PyObject_GetAttrString(type, "__module__"); if (moduleName == NULL || !PyUnicode_Check(moduleName)) { - Py_DECREF(moduleName); + Py_XDECREF(moduleName); err = PyFile_WriteString("", f); } else { -- cgit v1.2.1 From 459f2d304e64d475c9c84fcbc0e3a70c781b85c2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 May 2011 07:53:28 -0500 Subject: remove unused string WILFE attribute --- Python/marshal.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 73d4f374cd..f66b765b7d 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -60,7 +60,6 @@ typedef struct { PyObject *str; char *ptr; char *end; - PyObject *strings; /* dict on marshal, list on unmarshal */ int version; } WFILE; @@ -444,7 +443,6 @@ PyMarshal_WriteLongToFile(long x, FILE *fp, int version) wf.fp = fp; wf.error = WFERR_OK; wf.depth = 0; - wf.strings = NULL; wf.version = version; w_long(x, &wf); } @@ -456,10 +454,8 @@ PyMarshal_WriteObjectToFile(PyObject *x, FILE *fp, int version) wf.fp = fp; wf.error = WFERR_OK; wf.depth = 0; - wf.strings = (version > 0) ? PyDict_New() : NULL; wf.version = version; w_object(x, &wf); - Py_XDECREF(wf.strings); } typedef WFILE RFILE; /* Same struct with different invariants */ @@ -1041,7 +1037,6 @@ PyMarshal_ReadShortFromFile(FILE *fp) RFILE rf; assert(fp); rf.fp = fp; - rf.strings = NULL; rf.end = rf.ptr = NULL; return r_short(&rf); } @@ -1051,7 +1046,6 @@ PyMarshal_ReadLongFromFile(FILE *fp) { RFILE rf; rf.fp = fp; - rf.strings = NULL; rf.ptr = rf.end = NULL; return r_long(&rf); } @@ -1112,11 +1106,9 @@ PyMarshal_ReadObjectFromFile(FILE *fp) RFILE rf; PyObject *result; rf.fp = fp; - rf.strings = PyList_New(0); rf.depth = 0; rf.ptr = rf.end = NULL; result = r_object(&rf); - Py_DECREF(rf.strings); return result; } @@ -1128,10 +1120,8 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) rf.fp = NULL; rf.ptr = str; rf.end = str + len; - rf.strings = PyList_New(0); rf.depth = 0; result = r_object(&rf); - Py_DECREF(rf.strings); return result; } @@ -1150,9 +1140,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) wf.error = WFERR_OK; wf.depth = 0; wf.version = version; - wf.strings = (version > 0) ? PyDict_New() : NULL; w_object(x, &wf); - Py_XDECREF(wf.strings); if (wf.str != NULL) { char *base = PyBytes_AS_STRING((PyBytesObject *)wf.str); if (wf.ptr - base > PY_SSIZE_T_MAX) { @@ -1242,10 +1230,8 @@ marshal_load(PyObject *self, PyObject *f) Py_DECREF(data); return NULL; } - rf.strings = PyList_New(0); rf.depth = 0; result = read_object(&rf); - Py_DECREF(rf.strings); Py_DECREF(data); return result; } @@ -1298,10 +1284,8 @@ marshal_loads(PyObject *self, PyObject *args) rf.fp = NULL; rf.ptr = s; rf.end = s + n; - rf.strings = PyList_New(0); rf.depth = 0; result = read_object(&rf); - Py_DECREF(rf.strings); PyBuffer_Release(&p); return result; } -- cgit v1.2.1 From 69ae509ca8e95a2fb717c6a12117e9e77bd44306 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 May 2011 09:08:01 -0500 Subject: try to use the same str object for all code filenames when compiling or unmarshalling (#12190) This should reduce memory usage. --- Python/compile.c | 27 +++++++++------------------ Python/marshal.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 18 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index d195967e7c..96d01cdcc8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -135,6 +135,7 @@ managed by compiler_enter_scope() and compiler_exit_scope(). struct compiler { const char *c_filename; + PyObject *c_filename_obj; struct symtable *c_st; PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; @@ -272,6 +273,9 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, if (!compiler_init(&c)) return NULL; c.c_filename = filename; + c.c_filename_obj = PyUnicode_DecodeFSDefault(filename); + if (!c.c_filename_obj) + goto finally; c.c_arena = arena; c.c_future = PyFuture_FromAST(mod, filename); if (c.c_future == NULL) @@ -324,6 +328,8 @@ compiler_free(struct compiler *c) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free(c->c_future); + if (c->c_filename_obj) + Py_DECREF(c->c_filename_obj); Py_DECREF(c->c_stack); } @@ -3361,7 +3367,7 @@ compiler_in_loop(struct compiler *c) { static int compiler_error(struct compiler *c, const char *errstr) { - PyObject *loc, *filename; + PyObject *loc; PyObject *u = NULL, *v = NULL; loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); @@ -3369,16 +3375,7 @@ compiler_error(struct compiler *c, const char *errstr) Py_INCREF(Py_None); loc = Py_None; } - if (c->c_filename != NULL) { - filename = PyUnicode_DecodeFSDefault(c->c_filename); - if (!filename) - goto exit; - } - else { - Py_INCREF(Py_None); - filename = Py_None; - } - u = Py_BuildValue("(NiiO)", filename, c->u->u_lineno, + u = Py_BuildValue("(OiiO)", c->c_filename_obj, c->u->u_lineno, c->u->u_col_offset, loc); if (!u) goto exit; @@ -3927,7 +3924,6 @@ makecode(struct compiler *c, struct assembler *a) PyObject *consts = NULL; PyObject *names = NULL; PyObject *varnames = NULL; - PyObject *filename = NULL; PyObject *name = NULL; PyObject *freevars = NULL; PyObject *cellvars = NULL; @@ -3951,10 +3947,6 @@ makecode(struct compiler *c, struct assembler *a) freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); - if (!filename) - goto error; - nlocals = PyDict_Size(c->u->u_varnames); flags = compute_code_flags(c); if (flags < 0) @@ -3974,14 +3966,13 @@ makecode(struct compiler *c, struct assembler *a) nlocals, stackdepth(c), flags, bytecode, consts, names, varnames, freevars, cellvars, - filename, c->u->u_name, + c->c_filename_obj, c->u->u_name, c->u->u_firstlineno, a->a_lnotab); error: Py_XDECREF(consts); Py_XDECREF(names); Py_XDECREF(varnames); - Py_XDECREF(filename); Py_XDECREF(name); Py_XDECREF(freevars); Py_XDECREF(cellvars); diff --git a/Python/marshal.c b/Python/marshal.c index f66b765b7d..7b327ade01 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -58,6 +58,7 @@ typedef struct { int depth; /* If fp == NULL, the following are valid: */ PyObject *str; + PyObject *current_filename; char *ptr; char *end; int version; @@ -976,6 +977,18 @@ r_object(RFILE *p) filename = r_object(p); if (filename == NULL) goto code_error; + if (PyUnicode_CheckExact(filename)) { + if (p->current_filename != NULL) { + if (!PyUnicode_Compare(filename, p->current_filename)) { + Py_DECREF(filename); + Py_INCREF(p->current_filename); + filename = p->current_filename; + } + } + else { + p->current_filename = filename; + } + } name = r_object(p); if (name == NULL) goto code_error; @@ -1037,6 +1050,7 @@ PyMarshal_ReadShortFromFile(FILE *fp) RFILE rf; assert(fp); rf.fp = fp; + rf.current_filename = NULL; rf.end = rf.ptr = NULL; return r_short(&rf); } @@ -1046,6 +1060,7 @@ PyMarshal_ReadLongFromFile(FILE *fp) { RFILE rf; rf.fp = fp; + rf.current_filename = NULL; rf.ptr = rf.end = NULL; return r_long(&rf); } @@ -1106,6 +1121,7 @@ PyMarshal_ReadObjectFromFile(FILE *fp) RFILE rf; PyObject *result; rf.fp = fp; + rf.current_filename = NULL; rf.depth = 0; rf.ptr = rf.end = NULL; result = r_object(&rf); @@ -1118,6 +1134,7 @@ PyMarshal_ReadObjectFromString(char *str, Py_ssize_t len) RFILE rf; PyObject *result; rf.fp = NULL; + rf.current_filename = NULL; rf.ptr = str; rf.end = str + len; rf.depth = 0; @@ -1214,6 +1231,7 @@ marshal_load(PyObject *self, PyObject *f) if (data == NULL) return NULL; rf.fp = NULL; + rf.current_filename = NULL; if (PyBytes_Check(data)) { rf.ptr = PyBytes_AS_STRING(data); rf.end = rf.ptr + PyBytes_GET_SIZE(data); @@ -1282,6 +1300,7 @@ marshal_loads(PyObject *self, PyObject *args) s = p.buf; n = p.len; rf.fp = NULL; + rf.current_filename = NULL; rf.ptr = s; rf.end = s + n; rf.depth = 0; -- cgit v1.2.1 From eae636eca28d40666c402f8844077fcd37467b62 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 27 May 2011 16:46:51 +0200 Subject: Revert my commit 7ba176c2f558: "Avoid useless "++" at the end of functions Warnings found by the Clang Static Analyzer." Most people prefer ++ at the end of functions. --- Python/compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 96d01cdcc8..34e7603b3a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3744,11 +3744,11 @@ assemble_lnotab(struct assembler *a, struct instr *i) a->a_lnotab_off += 2; if (d_bytecode) { *lnotab++ = d_bytecode; - *lnotab = d_lineno; + *lnotab++ = d_lineno; } else { /* First line of a block; def stmt, etc. */ *lnotab++ = 0; - *lnotab = d_lineno; + *lnotab++ = d_lineno; } a->a_lineno = i->i_lineno; a->a_lineno_off = a->a_offset; @@ -3793,7 +3793,7 @@ assemble_emit(struct assembler *a, struct instr *i) if (i->i_hasarg) { assert(size == 3 || size == 6); *code++ = arg & 0xff; - *code = arg >> 8; + *code++ = arg >> 8; } return 1; } -- cgit v1.2.1 From 21cba104ee05a4fe9df4e4b8a4424a4ac1af22a5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 May 2011 13:58:08 -0500 Subject: reflect with statements with multiple items in the AST (closes #12106) --- Python/Python-ast.c | 161 +++++++++++++++++++++++++++++++++++++++------------- Python/ast.c | 43 ++++++-------- Python/compile.c | 21 ++++--- Python/symtable.c | 16 ++++-- 4 files changed, 162 insertions(+), 79 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 6b1ea3cbab..2364db3071 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -95,8 +95,7 @@ static char *If_fields[]={ }; static PyTypeObject *With_type; static char *With_fields[]={ - "context_expr", - "optional_vars", + "items", "body", }; static PyTypeObject *Raise_type; @@ -392,6 +391,12 @@ static char *alias_fields[]={ "name", "asname", }; +static PyTypeObject *withitem_type; +static PyObject* ast2obj_withitem(void*); +static char *withitem_fields[]={ + "context_expr", + "optional_vars", +}; static int @@ -680,7 +685,7 @@ static int init_types(void) if (!While_type) return 0; If_type = make_type("If", stmt_type, If_fields, 3); if (!If_type) return 0; - With_type = make_type("With", stmt_type, With_fields, 3); + With_type = make_type("With", stmt_type, With_fields, 2); if (!With_type) return 0; Raise_type = make_type("Raise", stmt_type, Raise_fields, 2); if (!Raise_type) return 0; @@ -938,6 +943,8 @@ static int init_types(void) if (!keyword_type) return 0; alias_type = make_type("alias", &AST_type, alias_fields, 2); if (!alias_type) return 0; + withitem_type = make_type("withitem", &AST_type, withitem_fields, 2); + if (!withitem_type) return 0; initialized = 1; return 1; } @@ -960,6 +967,7 @@ static int obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena); static int obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena); static int obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena); static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena); +static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena); mod_ty Module(asdl_seq * body, PyArena *arena) @@ -1225,21 +1233,15 @@ If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int } stmt_ty -With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, int lineno, - int col_offset, PyArena *arena) +With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, PyArena + *arena) { stmt_ty p; - if (!context_expr) { - PyErr_SetString(PyExc_ValueError, - "field context_expr is required for With"); - return NULL; - } p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; p->kind = With_kind; - p->v.With.context_expr = context_expr; - p->v.With.optional_vars = optional_vars; + p->v.With.items = items; p->v.With.body = body; p->lineno = lineno; p->col_offset = col_offset; @@ -2135,6 +2137,23 @@ alias(identifier name, identifier asname, PyArena *arena) return p; } +withitem_ty +withitem(expr_ty context_expr, expr_ty optional_vars, PyArena *arena) +{ + withitem_ty p; + if (!context_expr) { + PyErr_SetString(PyExc_ValueError, + "field context_expr is required for withitem"); + return NULL; + } + p = (withitem_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->context_expr = context_expr; + p->optional_vars = optional_vars; + return p; +} + PyObject* ast2obj_mod(void* _o) @@ -2390,15 +2409,9 @@ ast2obj_stmt(void* _o) case With_kind: result = PyType_GenericNew(With_type, NULL, NULL); if (!result) goto failed; - value = ast2obj_expr(o->v.With.context_expr); + value = ast2obj_list(o->v.With.items, ast2obj_withitem); if (!value) goto failed; - if (PyObject_SetAttrString(result, "context_expr", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_expr(o->v.With.optional_vars); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "optional_vars", value) == - -1) + if (PyObject_SetAttrString(result, "items", value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.With.body, ast2obj_stmt); @@ -3370,6 +3383,35 @@ failed: return NULL; } +PyObject* +ast2obj_withitem(void* _o) +{ + withitem_ty o = (withitem_ty)_o; + PyObject *result = NULL, *value = NULL; + if (!o) { + Py_INCREF(Py_None); + return Py_None; + } + + result = PyType_GenericNew(withitem_type, NULL, NULL); + if (!result) return NULL; + value = ast2obj_expr(o->context_expr); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "context_expr", value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(o->optional_vars); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "optional_vars", value) == -1) + goto failed; + Py_DECREF(value); + return result; +failed: + Py_XDECREF(value); + Py_XDECREF(result); + return NULL; +} + int obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) @@ -4210,33 +4252,34 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) return 1; } if (isinstance) { - expr_ty context_expr; - expr_ty optional_vars; + asdl_seq* items; asdl_seq* body; - if (PyObject_HasAttrString(obj, "context_expr")) { + if (PyObject_HasAttrString(obj, "items")) { int res; - tmp = PyObject_GetAttrString(obj, "context_expr"); + Py_ssize_t len; + Py_ssize_t i; + tmp = PyObject_GetAttrString(obj, "items"); if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &context_expr, arena); - if (res != 0) goto failed; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "With field \"items\" must be a list, not a %.200s", tmp->ob_type->tp_name); + goto failed; + } + len = PyList_GET_SIZE(tmp); + items = asdl_seq_new(len, arena); + if (items == NULL) goto failed; + for (i = 0; i < len; i++) { + withitem_ty value; + res = obj2ast_withitem(PyList_GET_ITEM(tmp, i), &value, arena); + if (res != 0) goto failed; + asdl_seq_SET(items, i, value); + } Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from With"); + PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from With"); return 1; } - if (PyObject_HasAttrString(obj, "optional_vars")) { - int res; - tmp = PyObject_GetAttrString(obj, "optional_vars"); - if (tmp == NULL) goto failed; - res = obj2ast_expr(tmp, &optional_vars, arena); - if (res != 0) goto failed; - Py_XDECREF(tmp); - tmp = NULL; - } else { - optional_vars = NULL; - } if (PyObject_HasAttrString(obj, "body")) { int res; Py_ssize_t len; @@ -4262,8 +4305,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from With"); return 1; } - *out = With(context_expr, optional_vars, body, lineno, - col_offset, arena); + *out = With(items, body, lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6723,6 +6765,43 @@ failed: return 1; } +int +obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena) +{ + PyObject* tmp = NULL; + expr_ty context_expr; + expr_ty optional_vars; + + if (PyObject_HasAttrString(obj, "context_expr")) { + int res; + tmp = PyObject_GetAttrString(obj, "context_expr"); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &context_expr, arena); + if (res != 0) goto failed; + Py_XDECREF(tmp); + tmp = NULL; + } else { + PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from withitem"); + return 1; + } + if (PyObject_HasAttrString(obj, "optional_vars")) { + int res; + tmp = PyObject_GetAttrString(obj, "optional_vars"); + if (tmp == NULL) goto failed; + res = obj2ast_expr(tmp, &optional_vars, arena); + if (res != 0) goto failed; + Py_XDECREF(tmp); + tmp = NULL; + } else { + optional_vars = NULL; + } + *out = withitem(context_expr, optional_vars, arena); + return 0; +failed: + Py_XDECREF(tmp); + return 1; +} + static struct PyModuleDef _astmodule = { PyModuleDef_HEAD_INIT, "_ast" @@ -6940,6 +7019,8 @@ PyInit__ast(void) return NULL; if (PyDict_SetItemString(d, "alias", (PyObject*)alias_type) < 0) return NULL; + if (PyDict_SetItemString(d, "withitem", (PyObject*)withitem_type) < 0) + return NULL; return m; } diff --git a/Python/ast.c b/Python/ast.c index 5b12da80f2..882452b5f0 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2967,8 +2967,8 @@ ast_for_try_stmt(struct compiling *c, const node *n) } /* with_item: test ['as' expr] */ -static stmt_ty -ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content) +static withitem_ty +ast_for_with_item(struct compiling *c, const node *n) { expr_ty context_expr, optional_vars = NULL; @@ -2987,43 +2987,32 @@ ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content) } } - return With(context_expr, optional_vars, content, LINENO(n), - n->n_col_offset, c->c_arena); + return withitem(context_expr, optional_vars, c->c_arena); } /* with_stmt: 'with' with_item (',' with_item)* ':' suite */ static stmt_ty ast_for_with_stmt(struct compiling *c, const node *n) { - int i; - stmt_ty ret; - asdl_seq *inner; + int i, n_items; + asdl_seq *items, *body; REQ(n, with_stmt); - /* process the with items inside-out */ - i = NCH(n) - 1; - /* the suite of the innermost with item is the suite of the with stmt */ - inner = ast_for_suite(c, CHILD(n, i)); - if (!inner) - return NULL; - - for (;;) { - i -= 2; - ret = ast_for_with_item(c, CHILD(n, i), inner); - if (!ret) + n_items = (NCH(n) - 2) / 2; + items = asdl_seq_new(n_items, c->c_arena); + for (i = 1; i < NCH(n) - 2; i += 2) { + withitem_ty item = ast_for_with_item(c, CHILD(n, i)); + if (!item) return NULL; - /* was this the last item? */ - if (i == 1) - break; - /* if not, wrap the result so far in a new sequence */ - inner = asdl_seq_new(1, c->c_arena); - if (!inner) - return NULL; - asdl_seq_SET(inner, 0, ret); + asdl_seq_SET(items, (i - 1) / 2, item); } - return ret; + body = ast_for_suite(c, CHILD(n, NCH(n) - 1)); + if (!body) + return NULL; + + return With(items, body, LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty diff --git a/Python/compile.c b/Python/compile.c index 34e7603b3a..09983d21d6 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -179,7 +179,7 @@ static int compiler_in_loop(struct compiler *); static int inplace_binop(struct compiler *, operator_ty); static int expr_constant(struct compiler *, expr_ty); -static int compiler_with(struct compiler *, stmt_ty); +static int compiler_with(struct compiler *, stmt_ty, int); static int compiler_call_helper(struct compiler *c, int n, asdl_seq *args, asdl_seq *keywords, @@ -2341,7 +2341,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case Continue_kind: return compiler_continue(c); case With_kind: - return compiler_with(c, s); + return compiler_with(c, s, 0); } return 1; } @@ -3068,9 +3068,10 @@ expr_constant(struct compiler *c, expr_ty e) exit(*exc) */ static int -compiler_with(struct compiler *c, stmt_ty s) +compiler_with(struct compiler *c, stmt_ty s, int pos) { basicblock *block, *finally; + withitem_ty item = asdl_seq_GET(s->v.With.items, pos); assert(s->kind == With_kind); @@ -3080,7 +3081,7 @@ compiler_with(struct compiler *c, stmt_ty s) return 0; /* Evaluate EXPR */ - VISIT(c, expr, s->v.With.context_expr); + VISIT(c, expr, item->context_expr); ADDOP_JREL(c, SETUP_WITH, finally); /* SETUP_WITH pushes a finally block. */ @@ -3089,16 +3090,20 @@ compiler_with(struct compiler *c, stmt_ty s) return 0; } - if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + if (item->optional_vars) { + VISIT(c, expr, item->optional_vars); } else { /* Discard result from context.__enter__() */ ADDOP(c, POP_TOP); } - /* BLOCK code */ - VISIT_SEQ(c, stmt, s->v.With.body); + pos++; + if (pos == asdl_seq_LEN(s->v.With.items)) + /* BLOCK code */ + VISIT_SEQ(c, stmt, s->v.With.body) + else if (!compiler_with(c, s, pos)) + return 0; /* End of try block; start the finally block */ ADDOP(c, POP_BLOCK); diff --git a/Python/symtable.c b/Python/symtable.c index 8040665b58..d2762541fe 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -185,6 +185,7 @@ static int symtable_visit_params(struct symtable *st, asdl_seq *args); static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args); static int symtable_implicit_arg(struct symtable *st, int pos); static int symtable_visit_annotations(struct symtable *st, stmt_ty s); +static int symtable_visit_withitem(struct symtable *st, withitem_ty item); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -1305,10 +1306,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) /* nothing to do here */ break; case With_kind: - VISIT(st, expr, s->v.With.context_expr); - if (s->v.With.optional_vars) { - VISIT(st, expr, s->v.With.optional_vars); - } + VISIT_SEQ(st, withitem, s->v.With.items); VISIT_SEQ(st, stmt, s->v.With.body); break; } @@ -1540,6 +1538,16 @@ symtable_visit_excepthandler(struct symtable *st, excepthandler_ty eh) return 1; } +static int +symtable_visit_withitem(struct symtable *st, withitem_ty item) +{ + VISIT(st, expr, item->context_expr); + if (item->optional_vars) { + VISIT(st, expr, item->optional_vars); + } + return 1; +} + static int symtable_visit_alias(struct symtable *st, alias_ty a) -- cgit v1.2.1 From 3e849018fb1479352d59e40376e56db9bb1e4eaa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 27 May 2011 14:01:01 -0500 Subject: bump ast version --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2364db3071..f076c7e964 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 0daa6ba25d9b. + __version__ 9b11cc4e2918. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6818,7 +6818,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "0daa6ba25d9b") < 0) + if (PyModule_AddStringConstant(m, "__version__", "9b11cc4e2918") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From 6d1f6c22f99d5c3c7df1682b77d8dc4266bc3bf3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 29 May 2011 11:43:10 -0500 Subject: unify TryExcept and TryFinally (closes #12199) --- Python/Python-ast.c | 132 ++++++++++++---------------------------------------- Python/ast.c | 22 ++------- Python/compile.c | 34 ++++++++++---- Python/symtable.c | 13 ++---- 4 files changed, 64 insertions(+), 137 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f076c7e964..66e09b71a1 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -103,15 +103,11 @@ static char *Raise_fields[]={ "exc", "cause", }; -static PyTypeObject *TryExcept_type; -static char *TryExcept_fields[]={ +static PyTypeObject *Try_type; +static char *Try_fields[]={ "body", "handlers", "orelse", -}; -static PyTypeObject *TryFinally_type; -static char *TryFinally_fields[]={ - "body", "finalbody", }; static PyTypeObject *Assert_type; @@ -689,11 +685,8 @@ static int init_types(void) if (!With_type) return 0; Raise_type = make_type("Raise", stmt_type, Raise_fields, 2); if (!Raise_type) return 0; - TryExcept_type = make_type("TryExcept", stmt_type, TryExcept_fields, 3); - if (!TryExcept_type) return 0; - TryFinally_type = make_type("TryFinally", stmt_type, TryFinally_fields, - 2); - if (!TryFinally_type) return 0; + Try_type = make_type("Try", stmt_type, Try_fields, 4); + if (!Try_type) return 0; Assert_type = make_type("Assert", stmt_type, Assert_fields, 2); if (!Assert_type) return 0; Import_type = make_type("Import", stmt_type, Import_fields, 1); @@ -1264,33 +1257,18 @@ Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena) } stmt_ty -TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, int lineno, - int col_offset, PyArena *arena) +Try(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse, asdl_seq * + finalbody, int lineno, int col_offset, PyArena *arena) { stmt_ty p; p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; - p->kind = TryExcept_kind; - p->v.TryExcept.body = body; - p->v.TryExcept.handlers = handlers; - p->v.TryExcept.orelse = orelse; - p->lineno = lineno; - p->col_offset = col_offset; - return p; -} - -stmt_ty -TryFinally(asdl_seq * body, asdl_seq * finalbody, int lineno, int col_offset, - PyArena *arena) -{ - stmt_ty p; - p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); - if (!p) - return NULL; - p->kind = TryFinally_kind; - p->v.TryFinally.body = body; - p->v.TryFinally.finalbody = finalbody; + p->kind = Try_kind; + p->v.Try.body = body; + p->v.Try.handlers = handlers; + p->v.Try.orelse = orelse; + p->v.Try.finalbody = finalbody; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -2434,35 +2412,25 @@ ast2obj_stmt(void* _o) goto failed; Py_DECREF(value); break; - case TryExcept_kind: - result = PyType_GenericNew(TryExcept_type, NULL, NULL); + case Try_kind: + result = PyType_GenericNew(Try_type, NULL, NULL); if (!result) goto failed; - value = ast2obj_list(o->v.TryExcept.body, ast2obj_stmt); + value = ast2obj_list(o->v.Try.body, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttrString(result, "body", value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(o->v.TryExcept.handlers, - ast2obj_excepthandler); + value = ast2obj_list(o->v.Try.handlers, ast2obj_excepthandler); if (!value) goto failed; if (PyObject_SetAttrString(result, "handlers", value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_list(o->v.TryExcept.orelse, ast2obj_stmt); + value = ast2obj_list(o->v.Try.orelse, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttrString(result, "orelse", value) == -1) goto failed; Py_DECREF(value); - break; - case TryFinally_kind: - result = PyType_GenericNew(TryFinally_type, NULL, NULL); - if (!result) goto failed; - value = ast2obj_list(o->v.TryFinally.body, ast2obj_stmt); - if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) - goto failed; - Py_DECREF(value); - value = ast2obj_list(o->v.TryFinally.finalbody, ast2obj_stmt); + value = ast2obj_list(o->v.Try.finalbody, ast2obj_stmt); if (!value) goto failed; if (PyObject_SetAttrString(result, "finalbody", value) == -1) goto failed; @@ -4343,7 +4311,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (*out == NULL) goto failed; return 0; } - isinstance = PyObject_IsInstance(obj, (PyObject*)TryExcept_type); + isinstance = PyObject_IsInstance(obj, (PyObject*)Try_type); if (isinstance == -1) { return 1; } @@ -4351,6 +4319,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* handlers; asdl_seq* orelse; + asdl_seq* finalbody; if (PyObject_HasAttrString(obj, "body")) { int res; @@ -4359,7 +4328,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) tmp = PyObject_GetAttrString(obj, "body"); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "TryExcept field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "Try field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); goto failed; } len = PyList_GET_SIZE(tmp); @@ -4374,7 +4343,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from TryExcept"); + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Try"); return 1; } if (PyObject_HasAttrString(obj, "handlers")) { @@ -4384,7 +4353,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) tmp = PyObject_GetAttrString(obj, "handlers"); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "TryExcept field \"handlers\" must be a list, not a %.200s", tmp->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "Try field \"handlers\" must be a list, not a %.200s", tmp->ob_type->tp_name); goto failed; } len = PyList_GET_SIZE(tmp); @@ -4399,7 +4368,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from TryExcept"); + PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from Try"); return 1; } if (PyObject_HasAttrString(obj, "orelse")) { @@ -4409,7 +4378,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) tmp = PyObject_GetAttrString(obj, "orelse"); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "TryExcept field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "Try field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); goto failed; } len = PyList_GET_SIZE(tmp); @@ -4424,45 +4393,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from TryExcept"); - return 1; - } - *out = TryExcept(body, handlers, orelse, lineno, col_offset, - arena); - if (*out == NULL) goto failed; - return 0; - } - isinstance = PyObject_IsInstance(obj, (PyObject*)TryFinally_type); - if (isinstance == -1) { - return 1; - } - if (isinstance) { - asdl_seq* body; - asdl_seq* finalbody; - - if (PyObject_HasAttrString(obj, "body")) { - int res; - Py_ssize_t len; - Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); - if (tmp == NULL) goto failed; - if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "TryFinally field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); - goto failed; - } - len = PyList_GET_SIZE(tmp); - body = asdl_seq_new(len, arena); - if (body == NULL) goto failed; - for (i = 0; i < len; i++) { - stmt_ty value; - res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena); - if (res != 0) goto failed; - asdl_seq_SET(body, i, value); - } - Py_XDECREF(tmp); - tmp = NULL; - } else { - PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from TryFinally"); + PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from Try"); return 1; } if (PyObject_HasAttrString(obj, "finalbody")) { @@ -4472,7 +4403,7 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) tmp = PyObject_GetAttrString(obj, "finalbody"); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { - PyErr_Format(PyExc_TypeError, "TryFinally field \"finalbody\" must be a list, not a %.200s", tmp->ob_type->tp_name); + PyErr_Format(PyExc_TypeError, "Try field \"finalbody\" must be a list, not a %.200s", tmp->ob_type->tp_name); goto failed; } len = PyList_GET_SIZE(tmp); @@ -4487,10 +4418,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"finalbody\" missing from TryFinally"); + PyErr_SetString(PyExc_TypeError, "required field \"finalbody\" missing from Try"); return 1; } - *out = TryFinally(body, finalbody, lineno, col_offset, arena); + *out = Try(body, handlers, orelse, finalbody, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6853,10 +6785,8 @@ PyInit__ast(void) NULL; if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return NULL; - if (PyDict_SetItemString(d, "TryExcept", (PyObject*)TryExcept_type) < - 0) return NULL; - if (PyDict_SetItemString(d, "TryFinally", (PyObject*)TryFinally_type) < - 0) return NULL; + if (PyDict_SetItemString(d, "Try", (PyObject*)Try_type) < 0) return + NULL; if (PyDict_SetItemString(d, "Assert", (PyObject*)Assert_type) < 0) return NULL; if (PyDict_SetItemString(d, "Import", (PyObject*)Import_type) < 0) diff --git a/Python/ast.c b/Python/ast.c index 882452b5f0..485b7d64d2 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2893,7 +2893,7 @@ ast_for_try_stmt(struct compiling *c, const node *n) { const int nch = NCH(n); int n_except = (nch - 3)/3; - asdl_seq *body, *orelse = NULL, *finally = NULL; + asdl_seq *body, *handlers = NULL, *orelse = NULL, *finally = NULL; REQ(n, try_stmt); @@ -2934,9 +2934,8 @@ ast_for_try_stmt(struct compiling *c, const node *n) if (n_except > 0) { int i; - stmt_ty except_st; /* process except statements to create a try ... except */ - asdl_seq *handlers = asdl_seq_new(n_except, c->c_arena); + handlers = asdl_seq_new(n_except, c->c_arena); if (handlers == NULL) return NULL; @@ -2947,23 +2946,10 @@ ast_for_try_stmt(struct compiling *c, const node *n) return NULL; asdl_seq_SET(handlers, i, e); } - - except_st = TryExcept(body, handlers, orelse, LINENO(n), - n->n_col_offset, c->c_arena); - if (!finally) - return except_st; - - /* if a 'finally' is present too, we nest the TryExcept within a - TryFinally to emulate try ... except ... finally */ - body = asdl_seq_new(1, c->c_arena); - if (body == NULL) - return NULL; - asdl_seq_SET(body, 0, except_st); } - /* must be a try ... finally (except clauses are in body, if any exist) */ - assert(finally != NULL); - return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena); + assert(finally != NULL || asdl_seq_LEN(handlers)); + return Try(body, handlers, orelse, finally, LINENO(n), n->n_col_offset, c->c_arena); } /* with_item: test ['as' expr] */ diff --git a/Python/compile.c b/Python/compile.c index d24528b236..b655c2523a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -185,6 +185,7 @@ static int compiler_call_helper(struct compiler *c, int n, asdl_seq *keywords, expr_ty starargs, expr_ty kwargs); +static int compiler_try_except(struct compiler *, stmt_ty); static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -1898,7 +1899,13 @@ compiler_try_finally(struct compiler *c, stmt_ty s) compiler_use_next_block(c, body); if (!compiler_push_fblock(c, FINALLY_TRY, body)) return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.body); + if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { + if (!compiler_try_except(c, s)) + return 0; + } + else { + VISIT_SEQ(c, stmt, s->v.Try.body); + } ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); @@ -1906,7 +1913,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) compiler_use_next_block(c, end); if (!compiler_push_fblock(c, FINALLY_END, end)) return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); + VISIT_SEQ(c, stmt, s->v.Try.finalbody); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, end); @@ -1960,15 +1967,15 @@ compiler_try_except(struct compiler *c, stmt_ty s) compiler_use_next_block(c, body); if (!compiler_push_fblock(c, EXCEPT, body)) return 0; - VISIT_SEQ(c, stmt, s->v.TryExcept.body); + VISIT_SEQ(c, stmt, s->v.Try.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, EXCEPT, body); ADDOP_JREL(c, JUMP_FORWARD, orelse); - n = asdl_seq_LEN(s->v.TryExcept.handlers); + n = asdl_seq_LEN(s->v.Try.handlers); compiler_use_next_block(c, except); for (i = 0; i < n; i++) { excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( - s->v.TryExcept.handlers, i); + s->v.Try.handlers, i); if (!handler->v.ExceptHandler.type && i < n-1) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = 0; @@ -2055,11 +2062,20 @@ compiler_try_except(struct compiler *c, stmt_ty s) } ADDOP(c, END_FINALLY); compiler_use_next_block(c, orelse); - VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); + VISIT_SEQ(c, stmt, s->v.Try.orelse); compiler_use_next_block(c, end); return 1; } +static int +compiler_try(struct compiler *c, stmt_ty s) { + if (s->v.Try.finalbody && asdl_seq_LEN(s->v.Try.finalbody)) + return compiler_try_finally(c, s); + else + return compiler_try_except(c, s); +} + + static int compiler_import_as(struct compiler *c, identifier name, identifier asname) { @@ -2307,10 +2323,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) } ADDOP_I(c, RAISE_VARARGS, n); break; - case TryExcept_kind: - return compiler_try_except(c, s); - case TryFinally_kind: - return compiler_try_finally(c, s); + case Try_kind: + return compiler_try(c, s); case Assert_kind: return compiler_assert(c, s); case Import_kind: diff --git a/Python/symtable.c b/Python/symtable.c index d2762541fe..e31a2ebb39 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1211,14 +1211,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } } break; - case TryExcept_kind: - VISIT_SEQ(st, stmt, s->v.TryExcept.body); - VISIT_SEQ(st, stmt, s->v.TryExcept.orelse); - VISIT_SEQ(st, excepthandler, s->v.TryExcept.handlers); - break; - case TryFinally_kind: - VISIT_SEQ(st, stmt, s->v.TryFinally.body); - VISIT_SEQ(st, stmt, s->v.TryFinally.finalbody); + case Try_kind: + VISIT_SEQ(st, stmt, s->v.Try.body); + VISIT_SEQ(st, stmt, s->v.Try.orelse); + VISIT_SEQ(st, excepthandler, s->v.Try.handlers); + VISIT_SEQ(st, stmt, s->v.Try.finalbody); break; case Assert_kind: VISIT(st, expr, s->v.Assert.test); -- cgit v1.2.1 From 8ba4624df8c09a4de6be4732caac2283891789f5 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 29 May 2011 11:45:29 -0500 Subject: bump ast version --- Python/Python-ast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 66e09b71a1..b597626463 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 9b11cc4e2918. + __version__ e0e663132363. This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -6750,7 +6750,7 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "9b11cc4e2918") < 0) + if (PyModule_AddStringConstant(m, "__version__", "e0e663132363") < 0) return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; -- cgit v1.2.1 From dbea271885eccda0db2e5248fd932cc56ec8a495 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 3 Jun 2011 17:50:16 -0500 Subject: some horrible preprocessing tricks to automatically update the tag --- Python/import.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 1f28d2233d..aaf649f858 100644 --- a/Python/import.c +++ b/Python/import.c @@ -110,8 +110,12 @@ typedef unsigned short mode_t; TAG and PYC_TAG_UNICODE must change for each major Python release. The magic number will take care of any bytecode changes that occur during development. */ +#define QUOTE(arg) #arg +#define STRIFY(name) QUOTE(name) +#define MAJOR STRIFY(PY_MAJOR_VERSION) +#define MINOR STRIFY(PY_MINOR_VERSION) #define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) -#define TAG "cpython-32" +#define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" static const Py_UNICODE CACHEDIR_UNICODE[] = { '_', '_', 'p', 'y', 'c', 'a', 'c', 'h', 'e', '_', '_', '\0'}; @@ -119,7 +123,11 @@ static const Py_UNICODE CACHEDIR_UNICODE[] = { static long pyc_magic = MAGIC; static const char *pyc_tag = TAG; static const Py_UNICODE PYC_TAG_UNICODE[] = { - 'c', 'p', 'y', 't', 'h', 'o', 'n', '-', '3', '2', '\0'}; + 'c', 'p', 'y', 't', 'h', 'o', 'n', '-', PY_MAJOR_VERSION + 48, PY_MINOR_VERSION + 48, '\0'}; +#undef QUOTE +#undef STRIFY +#undef MAJOR +#undef MINOR /* See _PyImport_FixupExtensionObject() below */ static PyObject *extensions = NULL; -- cgit v1.2.1 From 76e229fd30ea1520a581971429237c57131af241 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 5 Jun 2011 22:04:07 -0500 Subject: greatly improve argument parsing error messages (closes #12265) --- Python/ceval.c | 303 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 166 insertions(+), 137 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 5627e83999..f1f4c70da1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3045,6 +3045,63 @@ exit_eval_frame: return retval; } +static void +positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +{ + int plural; + int kwonly_given = 0; + int atleast = co->co_argcount - defcount; + int i; + PyObject *sig, *kwonly_sig; + + if (given == -1) { + given = 0; + for (i = 0; i < co->co_argcount; i++) + if (GETLOCAL(i)) + given++; + } + for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++) + if (GETLOCAL(i)) + kwonly_given++; + if (co->co_flags & CO_VARARGS) { + plural = atleast != 1; + sig = PyUnicode_FromFormat("at least %d", atleast); + } + else if (defcount) { + plural = 1; + sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount); + } + else { + plural = co->co_argcount != 1; + sig = PyUnicode_FromFormat("%d", co->co_argcount); + } + if (sig == NULL) + return; + if (kwonly_given) { + const char *format = " positional argument%s (and %d keyword-only argument%s)"; + kwonly_sig = PyUnicode_FromFormat(format, given != 1 ? "s" : "", kwonly_given, + kwonly_given != 1 ? "s" : ""); + if (kwonly_sig == NULL) { + Py_DECREF(sig); + return; + } + } + else { + /* This will not fail. */ + kwonly_sig = PyUnicode_FromString(""); + } + PyErr_Format(PyExc_TypeError, + "%U() takes %U positional argument%s but %d%U %s given", + co->co_name, + sig, + plural ? "s" : "", + given, + kwonly_sig, + given == 1 && !kwonly_given ? "was" : "were"); + Py_DECREF(sig); + Py_DECREF(kwonly_sig); +} + /* This is gonna seem *real weird*, but if you put some other code between PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust the test in the if statements in Misc/gdbinit (pystack and pystackv). */ @@ -3061,6 +3118,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, PyThreadState *tstate = PyThreadState_GET(); PyObject *x, *u; int total_args = co->co_argcount + co->co_kwonlyargcount; + int i; + int n = argcount; + PyObject *kwdict = NULL; if (globals == NULL) { PyErr_SetString(PyExc_SystemError, @@ -3077,161 +3137,130 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, fastlocals = f->f_localsplus; freevars = f->f_localsplus + co->co_nlocals; - if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { - int i; - int n = argcount; - PyObject *kwdict = NULL; - if (co->co_flags & CO_VARKEYWORDS) { - kwdict = PyDict_New(); - if (kwdict == NULL) - goto fail; - i = total_args; - if (co->co_flags & CO_VARARGS) - i++; - SETLOCAL(i, kwdict); - } - if (argcount > co->co_argcount) { - if (!(co->co_flags & CO_VARARGS)) { - PyErr_Format(PyExc_TypeError, - "%U() takes %s %d " - "positional argument%s (%d given)", - co->co_name, - defcount ? "at most" : "exactly", - co->co_argcount, - co->co_argcount == 1 ? "" : "s", - argcount + kwcount); - goto fail; - } - n = co->co_argcount; - } - for (i = 0; i < n; i++) { + /* Parse arguments. */ + if (co->co_flags & CO_VARKEYWORDS) { + kwdict = PyDict_New(); + if (kwdict == NULL) + goto fail; + i = total_args; + if (co->co_flags & CO_VARARGS) + i++; + SETLOCAL(i, kwdict); + } + if (argcount > co->co_argcount) + n = co->co_argcount; + for (i = 0; i < n; i++) { + x = args[i]; + Py_INCREF(x); + SETLOCAL(i, x); + } + if (co->co_flags & CO_VARARGS) { + u = PyTuple_New(argcount - n); + if (u == NULL) + goto fail; + SETLOCAL(total_args, u); + for (i = n; i < argcount; i++) { x = args[i]; Py_INCREF(x); - SETLOCAL(i, x); + PyTuple_SET_ITEM(u, i-n, x); } - if (co->co_flags & CO_VARARGS) { - u = PyTuple_New(argcount - n); - if (u == NULL) - goto fail; - SETLOCAL(total_args, u); - for (i = n; i < argcount; i++) { - x = args[i]; - Py_INCREF(x); - PyTuple_SET_ITEM(u, i-n, x); - } + } + for (i = 0; i < kwcount; i++) { + PyObject **co_varnames; + PyObject *keyword = kws[2*i]; + PyObject *value = kws[2*i + 1]; + int j; + if (keyword == NULL || !PyUnicode_Check(keyword)) { + PyErr_Format(PyExc_TypeError, + "%U() keywords must be strings", + co->co_name); + goto fail; } - for (i = 0; i < kwcount; i++) { - PyObject **co_varnames; - PyObject *keyword = kws[2*i]; - PyObject *value = kws[2*i + 1]; - int j; - if (keyword == NULL || !PyUnicode_Check(keyword)) { - PyErr_Format(PyExc_TypeError, - "%U() keywords must be strings", - co->co_name); - goto fail; - } - /* Speed hack: do raw pointer compares. As names are - normally interned this should almost always hit. */ - co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - if (nm == keyword) - goto kw_found; - } - /* Slow fallback, just in case */ - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - int cmp = PyObject_RichCompareBool( - keyword, nm, Py_EQ); - if (cmp > 0) - goto kw_found; - else if (cmp < 0) - goto fail; - } - if (j >= total_args && kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%U() got an unexpected " - "keyword argument '%S'", - co->co_name, - keyword); + /* Speed hack: do raw pointer compares. As names are + normally interned this should almost always hit. */ + co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + if (nm == keyword) + goto kw_found; + } + /* Slow fallback, just in case */ + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + int cmp = PyObject_RichCompareBool( + keyword, nm, Py_EQ); + if (cmp > 0) + goto kw_found; + else if (cmp < 0) goto fail; - } - PyDict_SetItem(kwdict, keyword, value); - continue; - kw_found: - if (GETLOCAL(j) != NULL) { - PyErr_Format(PyExc_TypeError, + } + if (j >= total_args && kwdict == NULL) { + PyErr_Format(PyExc_TypeError, + "%U() got an unexpected " + "keyword argument '%S'", + co->co_name, + keyword); + goto fail; + } + PyDict_SetItem(kwdict, keyword, value); + continue; + kw_found: + if (GETLOCAL(j) != NULL) { + PyErr_Format(PyExc_TypeError, "%U() got multiple " - "values for keyword " - "argument '%S'", + "values for argument '%S'", co->co_name, keyword); - goto fail; - } - Py_INCREF(value); - SETLOCAL(j, value); + goto fail; } - if (co->co_kwonlyargcount > 0) { - for (i = co->co_argcount; i < total_args; i++) { - PyObject *name; - if (GETLOCAL(i) != NULL) - continue; - name = PyTuple_GET_ITEM(co->co_varnames, i); - if (kwdefs != NULL) { - PyObject *def = PyDict_GetItem(kwdefs, name); - if (def) { - Py_INCREF(def); - SETLOCAL(i, def); - continue; - } - } - PyErr_Format(PyExc_TypeError, - "%U() needs keyword-only argument %S", - co->co_name, name); + Py_INCREF(value); + SETLOCAL(j, value); + } + if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { + positional_argument_error(co, argcount, defcount, fastlocals); + goto fail; + } + if (argcount < co->co_argcount) { + int m = co->co_argcount - defcount; + for (i = argcount; i < m; i++) { + if (GETLOCAL(i) == NULL) { + positional_argument_error(co, -1, defcount, fastlocals); goto fail; } } - if (argcount < co->co_argcount) { - int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - int j, given = 0; - for (j = 0; j < co->co_argcount; j++) - if (GETLOCAL(j)) - given++; - PyErr_Format(PyExc_TypeError, - "%U() takes %s %d " - "argument%s " - "(%d given)", - co->co_name, - ((co->co_flags & CO_VARARGS) || - defcount) ? "at least" - : "exactly", - m, m == 1 ? "" : "s", given); - goto fail; - } + if (n > m) + i = n - m; + else + i = 0; + for (; i < defcount; i++) { + if (GETLOCAL(m+i) == NULL) { + PyObject *def = defs[i]; + Py_INCREF(def); + SETLOCAL(m+i, def); } - if (n > m) - i = n - m; - else - i = 0; - for (; i < defcount; i++) { - if (GETLOCAL(m+i) == NULL) { - PyObject *def = defs[i]; + } + } + if (co->co_kwonlyargcount > 0) { + for (i = co->co_argcount; i < total_args; i++) { + PyObject *name; + if (GETLOCAL(i) != NULL) + continue; + name = PyTuple_GET_ITEM(co->co_varnames, i); + if (kwdefs != NULL) { + PyObject *def = PyDict_GetItem(kwdefs, name); + if (def) { Py_INCREF(def); - SETLOCAL(m+i, def); + SETLOCAL(i, def); + continue; } } + PyErr_Format(PyExc_TypeError, + "%U() requires keyword-only argument '%S'", + co->co_name, name); + goto fail; } } - else if (argcount > 0 || kwcount > 0) { - PyErr_Format(PyExc_TypeError, - "%U() takes no arguments (%d given)", - co->co_name, - argcount + kwcount); - goto fail; - } + /* Allocate and initialize storage for cell vars, and copy free vars into frame. This isn't too efficient right now. */ if (PyTuple_GET_SIZE(co->co_cellvars)) { -- cgit v1.2.1 From faf7f967781894e0af45064e95fdb6bc0b31f22c Mon Sep 17 00:00:00 2001 From: Brian Curtin Date: Thu, 9 Jun 2011 17:55:54 -0500 Subject: Removed a Windows 9x trick used before LoadLibraryExW. Windows 9x has long been unsupported and the result of GetFullPathName was not even being used in the first place. --- Python/dynload_win.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 9869f6ae8b..932a637680 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -185,28 +185,19 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, { HINSTANCE hDLL = NULL; - wchar_t pathbuf[260]; unsigned int old_mode; ULONG_PTR cookie = 0; - /* We use LoadLibraryEx so Windows looks for dependent DLLs - in directory of pathname first. However, Windows95 - can sometimes not work correctly unless the absolute - path is used. If GetFullPathName() fails, the LoadLibrary - will certainly fail too, so use its error code */ - + /* Don't display a message box when Python can't load a DLL */ old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - if (GetFullPathNameW(PyUnicode_AS_UNICODE(pathname), - sizeof(pathbuf) / sizeof(pathbuf[0]), - pathbuf, - NULL)) { - ULONG_PTR cookie = _Py_ActivateActCtx(); - /* XXX This call doesn't exist in Windows CE */ - hDLL = LoadLibraryExW(PyUnicode_AS_UNICODE(pathname), NULL, - LOAD_WITH_ALTERED_SEARCH_PATH); - _Py_DeactivateActCtx(cookie); - } + cookie = _Py_ActivateActCtx(); + /* We use LoadLibraryEx so Windows looks for dependent DLLs + in directory of pathname first. */ + /* XXX This call doesn't exist in Windows CE */ + hDLL = LoadLibraryExW(PyUnicode_AS_UNICODE(pathname), NULL, + LOAD_WITH_ALTERED_SEARCH_PATH); + _Py_DeactivateActCtx(cookie); /* restore old error mode settings */ SetErrorMode(old_mode); -- cgit v1.2.1 From ffc361118f1250d4c960b2c8d0ff469de0d0b259 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Jun 2011 19:42:22 -0500 Subject: use a invalid name for the __class__ closure for super() (closes #12370) This prevents the assignment of __class__ in the class body from breaking super. (Although a determined person could do locals()["@__class__"] = 4) --- Python/compile.c | 2 +- Python/symtable.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index b655c2523a..567b2302a9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1566,7 +1566,7 @@ compiler_class(struct compiler *c, stmt_ty s) return 0; } /* return the (empty) __class__ cell */ - str = PyUnicode_InternFromString("__class__"); + str = PyUnicode_InternFromString("@__class__"); if (str == NULL) { compiler_exit_scope(c); return 0; diff --git a/Python/symtable.c b/Python/symtable.c index e31a2ebb39..b82d8d5b31 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -225,10 +225,17 @@ symtable_new(void) struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { - struct symtable *st = symtable_new(); + struct symtable *st; asdl_seq *seq; int i; + if (__class__ == NULL) { + __class__ = PyUnicode_InternFromString("@__class__"); + if (__class__ == NULL) + return NULL; + } + + st = symtable_new(); if (st == NULL) return st; st->st_filename = filename; @@ -744,8 +751,6 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, } else { /* Special-case __class__ */ - if (!GET_IDENTIFIER(__class__)) - goto error; assert(PySet_Contains(local, __class__) == 1); if (PySet_Add(newbound, __class__) < 0) goto error; @@ -783,7 +788,7 @@ analyze_block(PySTEntryObject *ste, PyObject *bound, PyObject *free, NULL)) goto error; else if (ste->ste_type == ClassBlock && !analyze_cells(scopes, newfree, - "__class__")) + "@__class__")) goto error; /* Records the results of the analysis in the symbol table entry */ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, @@ -1143,8 +1148,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) return 0; - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, DEF_LOCAL) || + if (!symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); @@ -1417,8 +1421,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { - if (!GET_IDENTIFIER(__class__) || - !symtable_add_def(st, __class__, USE)) + if (!symtable_add_def(st, __class__, USE)) return 0; } break; -- cgit v1.2.1 From 18d2c7a85fe49dbac1177fffb6517b8093f8e23c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 19 Jun 2011 19:54:45 -0500 Subject: bump magic for super closure change --- Python/import.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index aaf649f858..9ec8cd8b84 100644 --- a/Python/import.c +++ b/Python/import.c @@ -102,6 +102,7 @@ typedef unsigned short mode_t; Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) tag: cpython-32 Python 3.2a2 3180 (add DELETE_DEREF) + Python 3.3a0 3190 __class__ super closure changed */ /* MAGIC must change whenever the bytecode emitted by the compiler may no @@ -114,7 +115,7 @@ typedef unsigned short mode_t; #define STRIFY(name) QUOTE(name) #define MAJOR STRIFY(PY_MAJOR_VERSION) #define MINOR STRIFY(PY_MINOR_VERSION) -#define MAGIC (3180 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3190 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" static const Py_UNICODE CACHEDIR_UNICODE[] = { -- cgit v1.2.1 From 1a17e5818c9c58989ffdd4d0e2931db9c66579a0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 20 Jun 2011 15:01:10 +0200 Subject: find_module_path_list() fails if _Py_fopen() failed and raised an exception (UnicodeEncodeError). --- Python/import.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 9ec8cd8b84..de5dc0ca41 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1908,6 +1908,10 @@ find_module_path_list(PyObject *fullname, PyObject *name, fp = _Py_fopen(filename, filemode); if (fp == NULL) { Py_DECREF(filename); + if (PyErr_Occurred()) { + Py_DECREF(prefix); + return NULL; + } continue; } match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name); -- cgit v1.2.1 From fab579dcbba91dc35f5f2b25fcf221736fff5e4b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 20 Jun 2011 15:16:55 +0200 Subject: call_find_module() handles dup() failure: raise an OSError exception --- Python/import.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index de5dc0ca41..19e975a593 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3567,6 +3567,10 @@ call_find_module(PyObject *name, PyObject *path_list) if (fd != -1) fd = dup(fd); fclose(fp); + if (fd == -1) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } fp = NULL; } if (fd != -1) { -- cgit v1.2.1 From cc1b48469f203e2e125a16c560f0eb7050fba626 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 24 Jun 2011 09:37:26 -0500 Subject: give the names of missing positional or keyword-only arguments (closes #12356) --- Python/ceval.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 23 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index f1f4c70da1..ac0707046a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3046,28 +3046,118 @@ exit_eval_frame: } static void -positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +format_missing(const char *kind, PyCodeObject *co, PyObject *names) +{ + int err; + Py_ssize_t len = PyList_GET_SIZE(names); + PyObject *name_str, *comma, *tail, *tmp; + + assert(PyList_CheckExact(names)); + assert(len >= 1); + /* Deal with the joys of natural language. */ + switch (len) { + case 1: + name_str = PyList_GET_ITEM(names, 0); + Py_INCREF(name_str); + break; + case 2: + name_str = PyUnicode_FromFormat("%U and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + break; + default: + tail = PyUnicode_FromFormat(", %U, and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + /* Chop off the last two objects in the list. This shouldn't actually + fail, but we can't be too careful. */ + err = PyList_SetSlice(names, len - 2, len, NULL); + if (err == -1) { + Py_DECREF(tail); + return; + } + /* Stitch everything up into a nice comma-separated list. */ + comma = PyUnicode_FromString(", "); + if (comma == NULL) { + Py_DECREF(tail); + return; + } + tmp = PyUnicode_Join(comma, names); + Py_DECREF(comma); + if (tmp == NULL) { + Py_DECREF(tail); + return; + } + name_str = PyUnicode_Concat(tmp, tail); + Py_DECREF(tmp); + Py_DECREF(tail); + break; + } + if (name_str == NULL) + return; + PyErr_Format(PyExc_TypeError, + "%U() missing %i required %s argument%s: %U", + co->co_name, + len, + kind, + len == 1 ? "" : "s", + name_str); + Py_DECREF(name_str); +} + +static void +missing_arguments(PyCodeObject *co, int missing, int defcount, + PyObject **fastlocals) +{ + int i, j = 0; + int start, end; + int positional = defcount != -1; + const char *kind = positional ? "positional" : "keyword-only"; + PyObject *missing_names; + + /* Compute the names of the arguments that are missing. */ + missing_names = PyList_New(missing); + if (missing_names == NULL) + return; + if (positional) { + start = 0; + end = co->co_argcount - defcount; + } + else { + start = co->co_argcount; + end = start + co->co_kwonlyargcount; + } + for (i = start; i < end; i++) { + if (GETLOCAL(i) == NULL) { + PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i); + PyObject *name = PyObject_Repr(raw); + if (name == NULL) { + Py_DECREF(missing_names); + return; + } + PyList_SET_ITEM(missing_names, j++, name); + } + } + assert(j == missing); + format_missing(kind, co, missing_names); + Py_DECREF(missing_names); +} + +static void +too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) { int plural; int kwonly_given = 0; - int atleast = co->co_argcount - defcount; int i; PyObject *sig, *kwonly_sig; - if (given == -1) { - given = 0; - for (i = 0; i < co->co_argcount; i++) - if (GETLOCAL(i)) - given++; - } + assert((co->co_flags & CO_VARARGS) == 0); + /* Count missing keyword-only args. */ for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++) - if (GETLOCAL(i)) + if (GETLOCAL(i) != NULL) kwonly_given++; - if (co->co_flags & CO_VARARGS) { - plural = atleast != 1; - sig = PyUnicode_FromFormat("at least %d", atleast); - } - else if (defcount) { + if (defcount) { + int atleast = co->co_argcount - defcount; plural = 1; sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount); } @@ -3089,6 +3179,7 @@ positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject ** else { /* This will not fail. */ kwonly_sig = PyUnicode_FromString(""); + assert(kwonly_sig != NULL); } PyErr_Format(PyExc_TypeError, "%U() takes %U positional argument%s but %d%U %s given", @@ -3217,16 +3308,18 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, SETLOCAL(j, value); } if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { - positional_argument_error(co, argcount, defcount, fastlocals); + too_many_positional(co, argcount, defcount, fastlocals); goto fail; } if (argcount < co->co_argcount) { int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - positional_argument_error(co, -1, defcount, fastlocals); - goto fail; - } + int missing = 0; + for (i = argcount; i < m; i++) + if (GETLOCAL(i) == NULL) + missing++; + if (missing) { + missing_arguments(co, missing, defcount, fastlocals); + goto fail; } if (n > m) i = n - m; @@ -3241,6 +3334,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } } if (co->co_kwonlyargcount > 0) { + int missing = 0; for (i = co->co_argcount; i < total_args; i++) { PyObject *name; if (GETLOCAL(i) != NULL) @@ -3254,9 +3348,10 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, continue; } } - PyErr_Format(PyExc_TypeError, - "%U() requires keyword-only argument '%S'", - co->co_name, name); + missing++; + } + if (missing) { + missing_arguments(co, missing, -1, fastlocals); goto fail; } } -- cgit v1.2.1 From 37cbd069c30e77278338b265655b9d9b37278fcd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 24 Jun 2011 20:52:27 +0200 Subject: Issue #12392: fix thread initialization on FreeBSD 6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On FreeBSD6, pthread_kill() doesn't work on the main thread before the creation of the first thread. Create therefore a dummy thread (no-op) a startup to initialize the pthread library. Add also a test for this use case, test written by Charles-François Natali. --- Python/thread_pthread.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index 09a0887bd4..fe9dde6f52 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -144,7 +144,10 @@ typedef struct { * Initialization. */ -#ifdef _HAVE_BSDI +/* On FreeBSD6, pthread_kill() doesn't work on the main thread before + the creation of the first thread */ +#if defined(_HAVE_BSDI) \ + || (defined(__FreeBSD__) && __FreeBSD_version < 700000) static void _noop(void) { -- cgit v1.2.1 From 78e7d230757093d24166ed820271a07ddf77d3e3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 25 Jun 2011 22:54:45 -0500 Subject: map cells to arg slots at code creation time (closes #12399) This removes nested loops in PyEval_EvalCodeEx. --- Python/ceval.c | 64 +++++++++++++++------------------------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index ac0707046a..33213fa72d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3357,56 +3357,24 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } /* Allocate and initialize storage for cell vars, and copy free - vars into frame. This isn't too efficient right now. */ - if (PyTuple_GET_SIZE(co->co_cellvars)) { - int i, j, nargs, found; - Py_UNICODE *cellname, *argname; + vars into frame. */ + for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { PyObject *c; - - nargs = total_args; - if (co->co_flags & CO_VARARGS) - nargs++; - if (co->co_flags & CO_VARKEYWORDS) - nargs++; - - /* Initialize each cell var, taking into account - cell vars that are initialized from arguments. - - Should arrange for the compiler to put cellvars - that are arguments at the beginning of the cellvars - list so that we can march over it more efficiently? - */ - for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { - cellname = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_cellvars, i)); - found = 0; - for (j = 0; j < nargs; j++) { - argname = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_varnames, j)); - if (Py_UNICODE_strcmp(cellname, argname) == 0) { - c = PyCell_New(GETLOCAL(j)); - if (c == NULL) - goto fail; - GETLOCAL(co->co_nlocals + i) = c; - found = 1; - break; - } - } - if (found == 0) { - c = PyCell_New(NULL); - if (c == NULL) - goto fail; - SETLOCAL(co->co_nlocals + i, c); - } - } + int arg; + /* Possibly account for the cell variable being an argument. */ + if (co->co_cell2arg != NULL && + (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG) + c = PyCell_New(GETLOCAL(arg)); + else + c = PyCell_New(NULL); + if (c == NULL) + goto fail; + SETLOCAL(co->co_nlocals + i, c); } - if (PyTuple_GET_SIZE(co->co_freevars)) { - int i; - for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { - PyObject *o = PyTuple_GET_ITEM(closure, i); - Py_INCREF(o); - freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; - } + for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; } if (co->co_flags & CO_GENERATOR) { -- cgit v1.2.1 From 08ea9b8b20b6fb77e2fca3026bca7301b2829e38 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 29 Jun 2011 15:27:14 -0500 Subject: remove VISIT_*_IN_BLOCK macros These are pointless because on error, all blocks will be finalized by symtable_dealloc. --- Python/symtable.c | 51 ++++++++++----------------------------------------- 1 file changed, 10 insertions(+), 41 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 232f02c500..f86575bdf4 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1029,12 +1029,6 @@ error: if (!symtable_visit_ ## TYPE((ST), (V))) \ return 0; -#define VISIT_IN_BLOCK(ST, TYPE, V, S) \ - if (!symtable_visit_ ## TYPE((ST), (V))) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } - #define VISIT_SEQ(ST, TYPE, SEQ) { \ int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ @@ -1045,18 +1039,6 @@ error: } \ } -#define VISIT_SEQ_IN_BLOCK(ST, TYPE, SEQ, S) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = 0; i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } \ - } \ -} - #define VISIT_SEQ_TAIL(ST, TYPE, SEQ, START) { \ int i; \ asdl_seq *seq = (SEQ); /* avoid variable capture */ \ @@ -1067,18 +1049,6 @@ error: } \ } -#define VISIT_SEQ_TAIL_IN_BLOCK(ST, TYPE, SEQ, START, S) { \ - int i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (i = (START); i < asdl_seq_LEN(seq); i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ - if (!symtable_visit_ ## TYPE((ST), elt)) { \ - symtable_exit_block((ST), (S)); \ - return 0; \ - } \ - } \ -} - #define VISIT_KWONLYDEFAULTS(ST, KW_DEFAULTS) { \ int i = 0; \ asdl_seq *seq = (KW_DEFAULTS); /* avoid variable capture */ \ @@ -1128,8 +1098,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) FunctionBlock, (void *)s, s->lineno, s->col_offset)) return 0; - VISIT_IN_BLOCK(st, arguments, s->v.FunctionDef.args, s); - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.FunctionDef.body, s); + VISIT(st, arguments, s->v.FunctionDef.args); + VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st, s)) return 0; break; @@ -1156,7 +1126,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) } tmp = st->st_private; st->st_private = s->v.ClassDef.name; - VISIT_SEQ_IN_BLOCK(st, stmt, s->v.ClassDef.body, s); + VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st, s)) return 0; @@ -1337,8 +1307,8 @@ symtable_visit_expr(struct symtable *st, expr_ty e) FunctionBlock, (void *)e, e->lineno, e->col_offset)) return 0; - VISIT_IN_BLOCK(st, arguments, e->v.Lambda.args, (void*)e); - VISIT_IN_BLOCK(st, expr, e->v.Lambda.body, (void*)e); + VISIT(st, arguments, e->v.Lambda.args); + VISIT(st, expr, e->v.Lambda.body); if (!symtable_exit_block(st, (void *)e)) return 0; break; @@ -1658,13 +1628,12 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, symtable_exit_block(st, (void *)e); return 0; } - VISIT_IN_BLOCK(st, expr, outermost->target, (void*)e); - VISIT_SEQ_IN_BLOCK(st, expr, outermost->ifs, (void*)e); - VISIT_SEQ_TAIL_IN_BLOCK(st, comprehension, - generators, 1, (void*)e); + VISIT(st, expr, outermost->target); + VISIT_SEQ(st, expr, outermost->ifs); + VISIT_SEQ_TAIL(st, comprehension, generators, 1); if (value) - VISIT_IN_BLOCK(st, expr, value, (void*)e); - VISIT_IN_BLOCK(st, expr, elt, (void*)e); + VISIT(st, expr, value); + VISIT(st, expr, elt); return symtable_exit_block(st, (void *)e); } -- cgit v1.2.1 From 507a021f5a83b200f01f531ab6a819a7134bc0cb Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 29 Jun 2011 22:52:39 -0500 Subject: store the current scope on the stack right away --- Python/symtable.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index f86575bdf4..82b1ebb7fa 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -899,17 +899,14 @@ symtable_warn(struct symtable *st, char *msg, int lineno) static int symtable_exit_block(struct symtable *st, void *ast) { - Py_ssize_t end; + Py_ssize_t size; - Py_CLEAR(st->st_cur); - end = PyList_GET_SIZE(st->st_stack) - 1; - if (end >= 0) { + st->st_cur = NULL; + size = PyList_GET_SIZE(st->st_stack); + if (size) { st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, - end); - if (st->st_cur == NULL) - return 0; - Py_INCREF(st->st_cur); - if (PySequence_DelItem(st->st_stack, end) < 0) + size - 2); + if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0) return 0; } return 1; @@ -919,23 +916,23 @@ static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, void *ast, int lineno, int col_offset) { - PySTEntryObject *prev = NULL; + PySTEntryObject *prev = NULL, *ste; - if (st->st_cur) { - prev = st->st_cur; - if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { - return 0; - } - Py_DECREF(st->st_cur); - } - st->st_cur = ste_new(st, name, block, ast, lineno, col_offset); - if (st->st_cur == NULL) + ste = ste_new(st, name, block, ast, lineno, col_offset); + if (ste == NULL) return 0; + if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) { + Py_DECREF(ste); + return 0; + } + prev = st->st_cur; + /* The entry is owned by the stack. Borrow it for st_cur. */ + Py_DECREF(ste); + st->st_cur = ste; if (block == ModuleBlock) st->st_global = st->st_cur->ste_symbols; if (prev) { - if (PyList_Append(prev->ste_children, - (PyObject *)st->st_cur) < 0) { + if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) { return 0; } } -- cgit v1.2.1 From 0c131a7b4cff5aa25bb4fd1757e4874efb4523f6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 2 Jul 2011 09:22:13 -0500 Subject: fix possibily uninitialized memory usage (closes #12474) --- Python/symtable.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/symtable.c b/Python/symtable.c index 82b1ebb7fa..a0bedfc767 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -904,10 +904,10 @@ symtable_exit_block(struct symtable *st, void *ast) st->st_cur = NULL; size = PyList_GET_SIZE(st->st_stack); if (size) { - st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, - size - 2); if (PyList_SetSlice(st->st_stack, size - 1, size, NULL) < 0) return 0; + if (--size) + st->st_cur = (PySTEntryObject *)PyList_GET_ITEM(st->st_stack, size - 1); } return 1; } -- cgit v1.2.1 From 635eaf2d0553df0712a7a9b332d1917f0aed4789 Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Sat, 2 Jul 2011 17:19:51 +0100 Subject: Removed breaking typo accidentally introduced during merge with 3.2. --- Python/marshal.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index b8d06ad286..c749bb3357 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1320,8 +1320,6 @@ marshal_load(PyObject *self, PyObject *f) { PyObject *data, *result; RFILE rf; - char *p; - int n; /* * Make a call to the read method, but read zero bytes. @@ -1338,12 +1336,10 @@ marshal_load(PyObject *self, PyObject *f) result = NULL; } else { - rf.strings = PyList_New(0); rf.depth = 0; rf.fp = NULL; rf.readable = f; result = read_object(&rf); - Py_DECREF(rf.strings); } Py_DECREF(data); return result; -- cgit v1.2.1 From 7533dccc560e295a63f029bde94d9679e3c7200e Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Sat, 2 Jul 2011 18:42:21 +0100 Subject: Correct uninitialized data problem in marshal code. --- Python/marshal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index c749bb3357..35fcd3afb3 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1339,6 +1339,7 @@ marshal_load(PyObject *self, PyObject *f) rf.depth = 0; rf.fp = NULL; rf.readable = f; + rf.current_filename = NULL; result = read_object(&rf); } Py_DECREF(data); -- cgit v1.2.1 From 2b7be477eff47f56618447c940977645a14c3017 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 16:48:31 -0500 Subject: convert generator exc state functions into static functions --- Python/ceval.c | 116 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 54 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 1dd0d49118..5a5e23c552 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -749,6 +749,9 @@ enum why_code { WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ }; +static void save_exc_state(PyThreadState *, PyFrameObject *); +static void swap_exc_state(PyThreadState *, PyFrameObject *); +static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *); static enum why_code do_raise(PyObject *, PyObject *); static int unpack_iterable(PyObject *, int, int, PyObject **); @@ -1110,54 +1113,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_XDECREF(traceback); \ } -#define SAVE_EXC_STATE() \ - { \ - PyObject *type, *value, *traceback; \ - Py_XINCREF(tstate->exc_type); \ - Py_XINCREF(tstate->exc_value); \ - Py_XINCREF(tstate->exc_traceback); \ - type = f->f_exc_type; \ - value = f->f_exc_value; \ - traceback = f->f_exc_traceback; \ - f->f_exc_type = tstate->exc_type; \ - f->f_exc_value = tstate->exc_value; \ - f->f_exc_traceback = tstate->exc_traceback; \ - Py_XDECREF(type); \ - Py_XDECREF(value); \ - Py_XDECREF(traceback); \ - } - -#define SWAP_EXC_STATE() \ - { \ - PyObject *tmp; \ - tmp = tstate->exc_type; \ - tstate->exc_type = f->f_exc_type; \ - f->f_exc_type = tmp; \ - tmp = tstate->exc_value; \ - tstate->exc_value = f->f_exc_value; \ - f->f_exc_value = tmp; \ - tmp = tstate->exc_traceback; \ - tstate->exc_traceback = f->f_exc_traceback; \ - f->f_exc_traceback = tmp; \ - } - -#define RESTORE_AND_CLEAR_EXC_STATE() \ - { \ - PyObject *type, *value, *tb; \ - type = tstate->exc_type; \ - value = tstate->exc_value; \ - tb = tstate->exc_traceback; \ - tstate->exc_type = f->f_exc_type; \ - tstate->exc_value = f->f_exc_value; \ - tstate->exc_traceback = f->f_exc_traceback; \ - f->f_exc_type = NULL; \ - f->f_exc_value = NULL; \ - f->f_exc_traceback = NULL; \ - Py_XDECREF(type); \ - Py_XDECREF(value); \ - Py_XDECREF(tb); \ - } - /* Start of code */ if (f == NULL) @@ -1236,11 +1191,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* We were in an except handler when we left, restore the exception state which was put aside (see YIELD_VALUE). */ - SWAP_EXC_STATE(); - } - else { - SAVE_EXC_STATE(); + swap_exc_state(tstate, f); } + else + save_exc_state(tstate, f); } #ifdef LLTRACE @@ -3033,9 +2987,9 @@ fast_yield: break; if (i == f->f_iblock) /* We did not create this exception. */ - RESTORE_AND_CLEAR_EXC_STATE() + restore_and_clear_exc_state(tstate, f); else - SWAP_EXC_STATE() + swap_exc_state(tstate, f); } if (tstate->use_tracing) { @@ -3453,6 +3407,60 @@ special_lookup(PyObject *o, char *meth, PyObject **cache) } +/* These 3 functions deal with the exception state of generators. */ + +static void +save_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *type, *value, *traceback; + Py_XINCREF(tstate->exc_type); + Py_XINCREF(tstate->exc_value); + Py_XINCREF(tstate->exc_traceback); + type = f->f_exc_type; + value = f->f_exc_value; + traceback = f->f_exc_traceback; + f->f_exc_type = tstate->exc_type; + f->f_exc_value = tstate->exc_value; + f->f_exc_traceback = tstate->exc_traceback; + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); +} + +static void +swap_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *tmp; + tmp = tstate->exc_type; + tstate->exc_type = f->f_exc_type; + f->f_exc_type = tmp; + tmp = tstate->exc_value; + tstate->exc_value = f->f_exc_value; + f->f_exc_value = tmp; + tmp = tstate->exc_traceback; + tstate->exc_traceback = f->f_exc_traceback; + f->f_exc_traceback = tmp; +} + +static void +restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *type, *value, *tb; + type = tstate->exc_type; + value = tstate->exc_value; + tb = tstate->exc_traceback; + tstate->exc_type = f->f_exc_type; + tstate->exc_value = f->f_exc_value; + tstate->exc_traceback = f->f_exc_traceback; + f->f_exc_type = NULL; + f->f_exc_value = NULL; + f->f_exc_traceback = NULL; + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); +} + + /* Logic for the raise statement (too complicated for inlining). This *consumes* a reference count to each of its arguments. */ static enum why_code -- cgit v1.2.1 From f409710160ebcab1fb89f5cb6cf0d8f733d07089 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 17:06:32 -0500 Subject: no one passes NULL here (or should anyway) --- Python/ceval.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 5a5e23c552..5c936376db 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1115,9 +1115,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Start of code */ - if (f == NULL) - return NULL; - /* push frame */ if (Py_EnterRecursiveCall("")) return NULL; -- cgit v1.2.1 From 841e3742a787ea782d53c357b9894deff2ad363d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 4 Jul 2011 13:48:30 +0200 Subject: Issue #9642: Fix filesystem encoding initialization: use the ANSI code page on Windows if the mbcs codec is not available, and fail with a fatal error if we cannot get the locale encoding (if nl_langinfo(CODESET) is not available) instead of using UTF-8. --- Python/bltinmodule.c | 5 +---- Python/pythonrun.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 19 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 4283566472..9adf530d27 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -24,12 +24,9 @@ int Py_HasFileSystemDefaultEncoding = 1; #elif defined(__APPLE__) const char *Py_FileSystemDefaultEncoding = "utf-8"; int Py_HasFileSystemDefaultEncoding = 1; -#elif defined(HAVE_LANGINFO_H) && defined(CODESET) +#else const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; -#else -const char *Py_FileSystemDefaultEncoding = "utf-8"; -int Py_HasFileSystemDefaultEncoding = 1; #endif static PyObject * diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 232d7befa0..5649e86c51 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -168,18 +168,25 @@ error: return NULL; } -#if defined(HAVE_LANGINFO_H) && defined(CODESET) static char* -get_codeset(void) +get_locale_encoding(void) { +#ifdef MS_WINDOWS + char codepage[100]; + PyOS_snprintf(codepage, sizeof(codepage), "cp%d", GetACP()); + return get_codec_name(codepage); +#elif defined(HAVE_LANGINFO_H) && defined(CODESET) char* codeset = nl_langinfo(CODESET); if (!codeset || codeset[0] == '\0') { PyErr_SetString(PyExc_ValueError, "CODESET is not set or empty"); return NULL; } return get_codec_name(codeset); -} +#else + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; #endif +} void Py_InitializeEx(int install_sigs) @@ -746,24 +753,17 @@ static int initfsencoding(PyInterpreterState *interp) { PyObject *codec; -#if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset = NULL; - - if (Py_FileSystemDefaultEncoding == NULL) { - /* On Unix, set the file system encoding according to the - user's preference, if the CODESET names a well-known - Python codec, and Py_FileSystemDefaultEncoding isn't - initialized by other means. */ - codeset = get_codeset(); - if (codeset == NULL) + + if (Py_FileSystemDefaultEncoding == NULL) + { + Py_FileSystemDefaultEncoding = get_locale_encoding(); + if (Py_FileSystemDefaultEncoding == NULL) Py_FatalError("Py_Initialize: Unable to get the locale encoding"); - Py_FileSystemDefaultEncoding = codeset; Py_HasFileSystemDefaultEncoding = 0; interp->fscodec_initialized = 1; return 0; } -#endif /* the encoding is mbcs, utf-8 or ascii */ codec = _PyCodec_Lookup(Py_FileSystemDefaultEncoding); -- cgit v1.2.1 From 627479288b2409511d6afbf8380797ede0319f8f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 4 Jul 2011 14:23:54 +0200 Subject: Issue #9642: Uniformize the tests on the availability of the mbcs codec Add a new HAVE_MBCS define. --- Python/bltinmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9adf530d27..291ef45e67 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -18,7 +18,7 @@ Don't forget to modify PyUnicode_DecodeFSDefault() if you touch any of the values for Py_FileSystemDefaultEncoding! */ -#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) +#ifdef HAVE_MBCS const char *Py_FileSystemDefaultEncoding = "mbcs"; int Py_HasFileSystemDefaultEncoding = 1; #elif defined(__APPLE__) -- cgit v1.2.1 From edf83ba036d27d56f63513a434766ce129f38610 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 4 Jul 2011 22:53:49 +0200 Subject: Issue #12469: partial revert of 024827a9db64, freebsd6 thread initialization * Don't create a thread at startup anymore to initialize the pthread library: it changes the behaviour of many functions related to signal handling like sigwait() * Reenable test_sigtimedwait_poll() on FreeBSD 6 --- Python/thread_pthread.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index fe9dde6f52..4b61e18941 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -144,10 +144,7 @@ typedef struct { * Initialization. */ -/* On FreeBSD6, pthread_kill() doesn't work on the main thread before - the creation of the first thread */ -#if defined(_HAVE_BSDI) \ - || (defined(__FreeBSD__) && __FreeBSD_version < 700000) +#if defined(_HAVE_BSDI) static void _noop(void) { -- cgit v1.2.1 From ea177211de1d338f04a2749b8d9b2a75b04b7e3a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 8 Jul 2011 23:37:39 +0200 Subject: Issue #11863: remove unused file Python/thread_wince.h --- Python/thread_wince.h | 136 -------------------------------------------------- 1 file changed, 136 deletions(-) delete mode 100644 Python/thread_wince.h (limited to 'Python') diff --git a/Python/thread_wince.h b/Python/thread_wince.h deleted file mode 100644 index 51ddc02f9a..0000000000 --- a/Python/thread_wince.h +++ /dev/null @@ -1,136 +0,0 @@ - -/* This code implemented by Mark Hammond (MHammond@skippinet.com.au) */ - -#include -#include -#include - -long PyThread_get_thread_ident(void); - -/* - * Change all headers to pure ANSI as no one will use K&R style on an - * NT - */ - -/* - * Initialization of the C package, should not be needed. - */ -static void PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - long rv; - int success = -1; - - dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - PyThread_init_thread(); - - rv = _beginthread(func, 0, arg); /* use default stack size */ - - if (rv != -1) { - success = 0; - dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident())); - } - - return success; -} - -/* - * Return the thread Id instead of an handle. The Id is said to uniquely identify the - * thread in the system - */ -long PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - - return GetCurrentThreadId(); -} - -void PyThread_exit_thread(void) -{ - dprintf(("%ld: PyThread_exit_thread called\n", PyThread_get_thread_ident())); - if (!initialized) - exit(0); - _endthread(); -} - -/* - * Lock support. It has to be implemented using Mutexes, as - * CE doesnt support semaphores. Therefore we use some hacks to - * simulate the non reentrant requirements of Python locks - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - HANDLE aLock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - aLock = CreateEvent(NULL, /* Security attributes */ - 0, /* Manual-Reset */ - 1, /* Is initially signalled */ - NULL); /* Name of event */ - - dprintf(("%ld: PyThread_allocate_lock() -> %p\n", PyThread_get_thread_ident(), aLock)); - - return (PyThread_type_lock) aLock; -} - -void PyThread_free_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_free_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - CloseHandle(aLock); -} - -/* - * Return 1 on success if the lock was acquired - * - * and 0 if the lock was not acquired. This means a 0 is returned - * if the lock has already been acquired by this thread! - */ -int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) -{ - int success = 1; - DWORD waitResult; - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n", PyThread_get_thread_ident(),aLock, waitflag)); - -#ifndef DEBUG - waitResult = WaitForSingleObject(aLock, (waitflag ? INFINITE : 0)); -#else - /* To aid in debugging, we regularly wake up. This allows us to - break into the debugger */ - while (TRUE) { - waitResult = WaitForSingleObject(aLock, waitflag ? 3000 : 0); - if (waitflag==0 || (waitflag && waitResult == WAIT_OBJECT_0)) - break; - } -#endif - - if (waitResult != WAIT_OBJECT_0) { - success = 0; /* We failed */ - } - - dprintf(("%ld: PyThread_acquire_lock(%p, %d) -> %d\n", PyThread_get_thread_ident(),aLock, waitflag, success)); - - return success; -} - -void PyThread_release_lock(PyThread_type_lock aLock) -{ - dprintf(("%ld: PyThread_release_lock(%p) called\n", PyThread_get_thread_ident(),aLock)); - - if (!SetEvent(aLock)) - dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n", PyThread_get_thread_ident(), aLock, GetLastError())); -} - - -- cgit v1.2.1 From aae9ecd9c079903bd0736541d806d07878b2b9c6 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 8 Jul 2011 23:47:50 +0200 Subject: Issue #11863: Remove support for legacy systems deprecated in Python 3.2 (following PEP 11). These systems are systems using Mach C Threads, SunOS lightweight processes, GNU pth threads and IRIX threads. --- Python/thread.c | 43 -------- Python/thread_cthread.h | 112 --------------------- Python/thread_lwp.h | 113 --------------------- Python/thread_sgi.h | 259 ------------------------------------------------ Python/thread_solaris.h | 130 ------------------------ 5 files changed, 657 deletions(-) delete mode 100644 Python/thread_cthread.h delete mode 100644 Python/thread_lwp.h delete mode 100644 Python/thread_sgi.h delete mode 100644 Python/thread_solaris.h (limited to 'Python') diff --git a/Python/thread.c b/Python/thread.c index c7d17d60e9..e55d34244e 100644 --- a/Python/thread.c +++ b/Python/thread.c @@ -26,18 +26,6 @@ #ifndef _POSIX_THREADS -#ifdef __sgi -#define SGI_THREADS -#endif - -#ifdef HAVE_THREAD_H -#define SOLARIS_THREADS -#endif - -#if defined(sun) && !defined(SOLARIS_THREADS) -#define SUN_LWP -#endif - /* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then enough of the Posix threads package is implemented to support python threads. @@ -93,37 +81,11 @@ PyThread_init_thread(void) or the size specified by the THREAD_STACK_SIZE macro. */ static size_t _pythread_stacksize = 0; -#ifdef SGI_THREADS -#error SGI Irix threads are now unsupported, and code will be removed in 3.3. -#include "thread_sgi.h" -#endif - -#ifdef SOLARIS_THREADS -#define PYTHREAD_NAME "solaris" -#include "thread_solaris.h" -#endif - -#ifdef SUN_LWP -#error SunOS lightweight processes are now unsupported, and code will be removed in 3.3. -#include "thread_lwp.h" -#endif - -#ifdef HAVE_PTH -#error GNU pth threads are now unsupported, and code will be removed in 3.3. -#include "thread_pth.h" -#undef _POSIX_THREADS -#endif - #ifdef _POSIX_THREADS #define PYTHREAD_NAME "pthread" #include "thread_pthread.h" #endif -#ifdef C_THREADS -#error Mach C Threads are now unsupported, and code will be removed in 3.3. -#include "thread_cthread.h" -#endif - #ifdef NT_THREADS #define PYTHREAD_NAME "nt" #include "thread_nt.h" @@ -134,11 +96,6 @@ static size_t _pythread_stacksize = 0; #include "thread_os2.h" #endif -#ifdef PLAN9_THREADS -#define PYTHREAD_NAME "plan9" -#include "thread_plan9.h" -#endif - /* #ifdef FOOBAR_THREADS #include "thread_foobar.h" diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h deleted file mode 100644 index 1b3e3904cd..0000000000 --- a/Python/thread_cthread.h +++ /dev/null @@ -1,112 +0,0 @@ - -#ifdef MACH_C_THREADS -#include -#endif - -#ifdef HURD_C_THREADS -#include -#endif - -/* - * Initialization. - */ -static void -PyThread__init_thread(void) -{ -#ifndef HURD_C_THREADS - /* Roland McGrath said this should not be used since this is - done while linking to threads */ - cthread_init(); -#else -/* do nothing */ - ; -#endif -} - -/* - * Thread support. - */ -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - /* looks like solaris detaches the thread to never rejoin - * so well do it here - */ - cthread_detach(cthread_fork((cthread_fn_t) func, arg)); - return success < 0 ? -1 : 0; -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - return (long) cthread_self(); -} - -void -PyThread_exit_thread(void) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - cthread_exit(0); -} - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - mutex_t lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = mutex_alloc(); - if (mutex_init(lock)) { - perror("mutex_init"); - free((void *) lock); - lock = 0; - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_free(lock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success = FALSE; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (waitflag) { /* blocking */ - mutex_lock((mutex_t)lock); - success = TRUE; - } else { /* non blocking */ - success = mutex_try_lock((mutex_t)lock); - } - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - mutex_unlock((mutex_t )lock); -} diff --git a/Python/thread_lwp.h b/Python/thread_lwp.h deleted file mode 100644 index ba7b37ad7e..0000000000 --- a/Python/thread_lwp.h +++ /dev/null @@ -1,113 +0,0 @@ - -#include -#include -#include - -#define STACKSIZE 1000 /* stacksize for a thread */ -#define NSTACKS 2 /* # stacks to be put in cache initially */ - -struct lock { - int lock_locked; - cv_t lock_condvar; - mon_t lock_monitor; -}; - - -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ - lwp_setstkcache(STACKSIZE, NSTACKS); -} - -/* - * Thread support. - */ - - -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - thread_t tid; - int success; - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg); - return success < 0 ? -1 : 0; -} - -long PyThread_get_thread_ident(void) -{ - thread_t tid; - if (!initialized) - PyThread_init_thread(); - if (lwp_self(&tid) < 0) - return -1; - return tid.thread_id; -} - -void PyThread_exit_thread(void) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - lwp_destroy(SELF); -} - -/* - * Lock support. - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - struct lock *lock; - extern char *malloc(size_t); - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (struct lock *) malloc(sizeof(struct lock)); - lock->lock_locked = 0; - (void) mon_create(&lock->lock_monitor); - (void) cv_create(&lock->lock_condvar, lock->lock_monitor); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mon_destroy(((struct lock *) lock)->lock_monitor); - free((char *) lock); -} - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - success = 0; - - (void) mon_enter(((struct lock *) lock)->lock_monitor); - if (waitflag) - while (((struct lock *) lock)->lock_locked) - cv_wait(((struct lock *) lock)->lock_condvar); - if (!((struct lock *) lock)->lock_locked) { - success = 1; - ((struct lock *) lock)->lock_locked = 1; - } - cv_broadcast(((struct lock *) lock)->lock_condvar); - mon_exit(((struct lock *) lock)->lock_monitor); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - (void) mon_enter(((struct lock *) lock)->lock_monitor); - ((struct lock *) lock)->lock_locked = 0; - cv_broadcast(((struct lock *) lock)->lock_condvar); - mon_exit(((struct lock *) lock)->lock_monitor); -} diff --git a/Python/thread_sgi.h b/Python/thread_sgi.h deleted file mode 100644 index 771ab2cc60..0000000000 --- a/Python/thread_sgi.h +++ /dev/null @@ -1,259 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define HDR_SIZE 2680 /* sizeof(ushdr_t) */ -#define MAXPROC 100 /* max # of threads that can be started */ - -static usptr_t *shared_arena; -static ulock_t count_lock; /* protection for some variables */ -static ulock_t wait_lock; /* lock used to wait for other threads */ -static int waiting_for_threads; /* protected by count_lock */ -static int nthreads; /* protected by count_lock */ -static int exit_status; -static int exiting; /* we're already exiting (for maybe_exit) */ -static pid_t my_pid; /* PID of main thread */ -static struct pidlist { - pid_t parent; - pid_t child; -} pidlist[MAXPROC]; /* PIDs of other threads; protected by count_lock */ -static int maxpidindex; /* # of PIDs in pidlist */ -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ -#ifdef USE_DL - long addr, size; -#endif /* USE_DL */ - - -#ifdef USE_DL - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); -#endif /* USE_DL */ - if (usconfig(CONF_INITUSERS, 16) < 0) - perror("usconfig - CONF_INITUSERS"); - my_pid = getpid(); /* so that we know which is the main thread */ - if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0) - perror("usconfig - CONF_ARENATYPE"); - usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */ -#ifdef Py_DEBUG - if (thread_debug & 4) - usconfig(CONF_LOCKTYPE, US_DEBUGPLUS); - else if (thread_debug & 2) - usconfig(CONF_LOCKTYPE, US_DEBUG); -#endif /* Py_DEBUG */ - if ((shared_arena = usinit(tmpnam(0))) == 0) - perror("usinit"); -#ifdef USE_DL - if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); -#endif /* USE_DL */ - if ((count_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (count_lock)"); - (void) usinitlock(count_lock); - if ((wait_lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock (wait_lock)"); - dprintf(("arena start: %p, arena size: %ld\n", shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena))); -} - -/* - * Thread support. - */ - -static void clean_threads(void) -{ - int i, j; - pid_t mypid, pid; - - /* clean up any exited threads */ - mypid = getpid(); - i = 0; - while (i < maxpidindex) { - if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) { - pid = waitpid(pid, 0, WNOHANG); - if (pid > 0) { - /* a thread has exited */ - pidlist[i] = pidlist[--maxpidindex]; - /* remove references to children of dead proc */ - for (j = 0; j < maxpidindex; j++) - if (pidlist[j].parent == pid) - pidlist[j].child = -1; - continue; /* don't increment i */ - } - } - i++; - } - /* clean up the list */ - i = 0; - while (i < maxpidindex) { - if (pidlist[i].child == -1) { - pidlist[i] = pidlist[--maxpidindex]; - continue; /* don't increment i */ - } - i++; - } -} - -long PyThread_start_new_thread(void (*func)(void *), void *arg) -{ -#ifdef USE_DL - long addr, size; - static int local_initialized = 0; -#endif /* USE_DL */ - int success = 0; /* init not needed when SOLARIS_THREADS and */ - /* C_THREADS implemented properly */ - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - switch (ussetlock(count_lock)) { - case 0: return 0; - case -1: perror("ussetlock (count_lock)"); - } - if (maxpidindex >= MAXPROC) - success = -1; - else { -#ifdef USE_DL - if (!local_initialized) { - if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0) - perror("usconfig - CONF_INITSIZE (check)"); - if (usconfig(CONF_INITSIZE, size) < 0) - perror("usconfig - CONF_INITSIZE (reset)"); - addr = (long) dl_getrange(size + HDR_SIZE); - dprintf(("trying to use addr %p-%p for sproc\n", - addr, addr+size)); - errno = 0; - if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && - errno != 0) - perror("usconfig - CONF_ATTACHADDR (set)"); - } -#endif /* USE_DL */ - clean_threads(); - if ((success = sproc(func, PR_SALL, arg)) < 0) - perror("sproc"); -#ifdef USE_DL - if (!local_initialized) { - if (usconfig(CONF_ATTACHADDR, addr) < 0) - /* reset address */ - perror("usconfig - CONF_ATTACHADDR (reset)"); - local_initialized = 1; - } -#endif /* USE_DL */ - if (success >= 0) { - nthreads++; - pidlist[maxpidindex].parent = getpid(); - pidlist[maxpidindex++].child = success; - dprintf(("pidlist[%d] = %d\n", - maxpidindex-1, success)); - } - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - return success; -} - -long PyThread_get_thread_ident(void) -{ - return getpid(); -} - -void PyThread_exit_thread(void) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - nthreads--; - if (getpid() == my_pid) { - /* main thread; wait for other threads to exit */ - exiting = 1; - waiting_for_threads = 1; - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - for (;;) { - if (nthreads < 0) { - dprintf(("really exit (%d)\n", exit_status)); - exit(exit_status); - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - dprintf(("waiting for other threads (%d)\n", nthreads)); - if (ussetlock(wait_lock) < 0) - perror("ussetlock (wait_lock)"); - if (ussetlock(count_lock) < 0) - perror("ussetlock (count_lock)"); - } - } - /* not the main thread */ - if (waiting_for_threads) { - dprintf(("main thread is waiting\n")); - if (usunsetlock(wait_lock) < 0) - perror("usunsetlock (wait_lock)"); - } - if (usunsetlock(count_lock) < 0) - perror("usunsetlock (count_lock)"); - _exit(0); -} - -/* - * Lock support. - */ -PyThread_type_lock PyThread_allocate_lock(void) -{ - ulock_t lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - if ((lock = usnewlock(shared_arena)) == NULL) - perror("usnewlock"); - (void) usinitlock(lock); - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - usfreelock((ulock_t) lock, shared_arena); -} - -int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - errno = 0; /* clear it just in case */ - if (waitflag) - success = ussetlock((ulock_t) lock); - else - success = uscsetlock((ulock_t) lock, 1); /* Try it once */ - if (success < 0) - perror(waitflag ? "ussetlock" : "uscsetlock"); - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (usunsetlock((ulock_t) lock) < 0) - perror("usunsetlock"); -} diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h deleted file mode 100644 index 1ce1cfcba9..0000000000 --- a/Python/thread_solaris.h +++ /dev/null @@ -1,130 +0,0 @@ - -#include -#include -#include -#include -#undef _POSIX_THREADS - - -/* - * Initialization. - */ -static void PyThread__init_thread(void) -{ -} - -/* - * Thread support. - */ -struct func_arg { - void (*func)(void *); - void *arg; -}; - -static void * -new_func(void *funcarg) -{ - void (*func)(void *); - void *arg; - - func = ((struct func_arg *) funcarg)->func; - arg = ((struct func_arg *) funcarg)->arg; - free(funcarg); - (*func)(arg); - return 0; -} - - -long -PyThread_start_new_thread(void (*func)(void *), void *arg) -{ - thread_t tid; - struct func_arg *funcarg; - - dprintf(("PyThread_start_new_thread called\n")); - if (!initialized) - PyThread_init_thread(); - funcarg = (struct func_arg *) malloc(sizeof(struct func_arg)); - funcarg->func = func; - funcarg->arg = arg; - if (thr_create(0, 0, new_func, funcarg, - THR_DETACHED | THR_NEW_LWP, &tid)) { - perror("thr_create"); - free((void *) funcarg); - return -1; - } - return tid; -} - -long -PyThread_get_thread_ident(void) -{ - if (!initialized) - PyThread_init_thread(); - return thr_self(); -} - -void -PyThread_exit_thread(void) -{ - dprintf(("PyThread_exit_thread called\n")); - if (!initialized) - exit(0); - thr_exit(0); -} - -/* - * Lock support. - */ -PyThread_type_lock -PyThread_allocate_lock(void) -{ - mutex_t *lock; - - dprintf(("PyThread_allocate_lock called\n")); - if (!initialized) - PyThread_init_thread(); - - lock = (mutex_t *) malloc(sizeof(mutex_t)); - if (mutex_init(lock, USYNC_THREAD, 0)) { - perror("mutex_init"); - free((void *) lock); - lock = 0; - } - dprintf(("PyThread_allocate_lock() -> %p\n", lock)); - return (PyThread_type_lock) lock; -} - -void -PyThread_free_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_free_lock(%p) called\n", lock)); - mutex_destroy((mutex_t *) lock); - free((void *) lock); -} - -int -PyThread_acquire_lock(PyThread_type_lock lock, int waitflag) -{ - int success; - - dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag)); - if (waitflag) - success = mutex_lock((mutex_t *) lock); - else - success = mutex_trylock((mutex_t *) lock); - if (success < 0) - perror(waitflag ? "mutex_lock" : "mutex_trylock"); - else - success = !success; /* solaris does it the other way round */ - dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success)); - return success; -} - -void -PyThread_release_lock(PyThread_type_lock lock) -{ - dprintf(("PyThread_release_lock(%p) called\n", lock)); - if (mutex_unlock((mutex_t *) lock)) - perror("mutex_unlock"); -} -- cgit v1.2.1 From 15f494d8ef787c1c6466938a6c0552bdb3c3d2da Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 15 Jul 2011 01:13:24 +0200 Subject: Py_BuildValue("C") supports non-BMP characters on narrow build Py_BuildValue("C") doesn't have to check the code point, PyUnicode_FromOrdinal() checks its input and now supports non-BMP characters (range U+10000-U+10FFFF). --- Python/modsupport.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Python') diff --git a/Python/modsupport.c b/Python/modsupport.c index 85b0d66358..08f5065883 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -292,11 +292,6 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) case 'C': { int i = va_arg(*p_va, int); - if (i < 0 || i > PyUnicode_GetMax()) { - PyErr_SetString(PyExc_OverflowError, - "%c arg not in range(0x110000)"); - return NULL; - } return PyUnicode_FromOrdinal(i); } -- cgit v1.2.1 From 2a0e1b24e9ddbfa621889f48dbbeaa370a8b4429 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 15 Jul 2011 21:10:13 -0500 Subject: remove ast.__version__ (closes #12273) --- Python/Python-ast.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index b597626463..96c6bf83fc 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1,14 +1,5 @@ /* File automatically generated by Parser/asdl_c.py. */ - -/* - __version__ e0e663132363. - - This module must be committed separately after each AST grammar change; - The __version__ number is set to the revision number of the commit - containing the grammar change. -*/ - #include "Python.h" #include "Python-ast.h" @@ -6750,8 +6741,6 @@ PyInit__ast(void) NULL; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return NULL; - if (PyModule_AddStringConstant(m, "__version__", "e0e663132363") < 0) - return NULL; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return NULL; if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) -- cgit v1.2.1 From 471239a1458855de653c1986ab17453b509944c9 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Sun, 17 Jul 2011 19:17:55 -0700 Subject: Make warnings accept a callable for showwarnings instead of restricting itself to just functions and methods (which allows built-in functions to be used, etc.). Closes issue #10271. Thanks to lekma for the bug report. --- Python/_warnings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 615a2d3217..f8a7175f92 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -409,10 +409,10 @@ warn_explicit(PyObject *category, PyObject *message, else { PyObject *res; - if (!PyMethod_Check(show_fxn) && !PyFunction_Check(show_fxn)) { + if (!PyCallable_Check(show_fxn)) { PyErr_SetString(PyExc_TypeError, "warnings.showwarning() must be set to a " - "function or method"); + "callable"); Py_DECREF(show_fxn); goto cleanup; } -- cgit v1.2.1 From 9ab49a8a88fec533bed7891464129e7603f530a4 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 17 Jul 2011 22:49:50 -0500 Subject: excise the remains of STOP_CODE, which hasn't done anything useful for years --- Python/ceval.c | 2 -- Python/makeopcodetargets.py | 3 --- 2 files changed, 5 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 6d493633a9..068da6f5f1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1347,8 +1347,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) x to NULL, err to nonzero, or why to anything but WHY_NOT, and that no operation that succeeds does this! */ - /* case STOP_CODE: this is an error! */ - TARGET(NOP) FAST_DISPATCH(); diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py index 5d8e5a9a46..d9a085552f 100755 --- a/Python/makeopcodetargets.py +++ b/Python/makeopcodetargets.py @@ -23,9 +23,6 @@ def write_contents(f): opcode = find_module("opcode") targets = ['_unknown_opcode'] * 256 for opname, op in opcode.opmap.items(): - if opname == "STOP_CODE": - # XXX opcode not implemented - continue targets[op] = "TARGET_%s" % opname f.write("static void *opcode_targets[256] = {\n") f.write(",\n".join([" &&%s" % s for s in targets])) -- cgit v1.2.1