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 From b4f0c255b55fb428481d238fede5cd449a2dbf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Sat, 23 Jul 2011 18:15:43 +0200 Subject: Issue 12620: Make pendingbusy flag static to Py_MakePendingCalls(). --- Python/ceval.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 068da6f5f1..1c9153e276 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -491,7 +491,6 @@ static struct { } pendingcalls[NPENDINGCALLS]; static int pendingfirst = 0; static int pendinglast = 0; -static char pendingbusy = 0; int Py_AddPendingCall(int (*func)(void *), void *arg) @@ -538,6 +537,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg) int Py_MakePendingCalls(void) { + static int busy = 0; int i; int r = 0; @@ -552,9 +552,9 @@ Py_MakePendingCalls(void) if (main_thread && PyThread_get_thread_ident() != main_thread) return 0; /* don't perform recursive pending calls */ - if (pendingbusy) + if (busy) return 0; - pendingbusy = 1; + busy = 1; /* perform a bounded number of calls, in case of recursion */ for (i=0; i Date: Fri, 29 Jul 2011 07:05:08 +0300 Subject: Issue #12380: PyArg_ParseTuple now accepts a bytearray for the 'c' format. As a side effect, this now allows the rjust, ljust and center methods of bytes and bytearray to accept a bytearray argument. Patch by Petri Lehtinen --- Python/getargs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 4b57153b88..c3da368604 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -828,6 +828,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) *p = PyBytes_AS_STRING(arg)[0]; + else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) + *p = PyByteArray_AS_STRING(arg)[0]; else return converterr("a byte string of length 1", arg, msgbuf, bufsize); break; -- cgit v1.2.1 From 704c68b66de17de0e13535f168c3d8ce77e8906a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Jul 2011 14:23:47 -0500 Subject: bytes should be verboten in sum() (fixes #12654) --- Python/bltinmodule.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 291ef45e67..82fb9ad165 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1888,6 +1888,11 @@ builtin_sum(PyObject *self, PyObject *args) Py_DECREF(iter); return NULL; } + if (PyBytes_Check(result)) { + PyErr_SetString(PyExc_TypeError, + "sum() can't sum bytes [use b''.join(seq) instead]"); + return NULL; + } if (PyByteArray_Check(result)) { PyErr_SetString(PyExc_TypeError, "sum() can't sum bytes [use b''.join(seq) instead]"); -- cgit v1.2.1 From 01aa4d1f405a7dd63d1b646f389ac948ddd11ff2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Jul 2011 14:24:29 -0500 Subject: bytes -> bytearray --- 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 82fb9ad165..064b8477f2 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1895,7 +1895,7 @@ builtin_sum(PyObject *self, PyObject *args) } if (PyByteArray_Check(result)) { PyErr_SetString(PyExc_TypeError, - "sum() can't sum bytes [use b''.join(seq) instead]"); + "sum() can't sum bytearray [use b''.join(seq) instead]"); Py_DECREF(iter); return NULL; } -- cgit v1.2.1 From 07813902f2659f99bec1aa46196244f12416d9a1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Jul 2011 22:43:45 -0500 Subject: plug refleak --- Python/bltinmodule.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 064b8477f2..152210b30b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1891,6 +1891,7 @@ builtin_sum(PyObject *self, PyObject *args) if (PyBytes_Check(result)) { PyErr_SetString(PyExc_TypeError, "sum() can't sum bytes [use b''.join(seq) instead]"); + Py_DECREF(iter); return NULL; } if (PyByteArray_Check(result)) { -- cgit v1.2.1 From 7bf0e0ea86f0b88e6cf0c6c6bd8a7113761769df Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 9 Aug 2011 16:08:39 -0500 Subject: add a asdl bytes type, so Bytes.s be properly typechecked --- Python/Python-ast.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 68b109722b..f6e345c916 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -573,6 +573,7 @@ static PyObject* ast2obj_object(void *o) } #define ast2obj_identifier ast2obj_object #define ast2obj_string ast2obj_object +#define ast2obj_bytes ast2obj_object static PyObject* ast2obj_int(long b) { @@ -610,6 +611,15 @@ static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena) return obj2ast_object(obj, out, arena); } +static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena) +{ + if (!PyBytes_CheckExact(obj)) { + PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes"); + return 1; + } + return obj2ast_object(obj, out, arena); +} + static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) { int i; @@ -1773,7 +1783,7 @@ Str(string s, int lineno, int col_offset, PyArena *arena) } expr_ty -Bytes(string s, int lineno, int col_offset, PyArena *arena) +Bytes(bytes s, int lineno, int col_offset, PyArena *arena) { expr_ty p; if (!s) { @@ -2804,7 +2814,7 @@ ast2obj_expr(void* _o) case Bytes_kind: result = PyType_GenericNew(Bytes_type, NULL, NULL); if (!result) goto failed; - value = ast2obj_string(o->v.Bytes.s); + value = ast2obj_bytes(o->v.Bytes.s); if (!value) goto failed; if (PyObject_SetAttrString(result, "s", value) == -1) goto failed; @@ -5509,13 +5519,13 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) return 1; } if (isinstance) { - string s; + bytes s; if (PyObject_HasAttrString(obj, "s")) { int res; tmp = PyObject_GetAttrString(obj, "s"); if (tmp == NULL) goto failed; - res = obj2ast_string(tmp, &s, arena); + res = obj2ast_bytes(tmp, &s, arena); if (res != 0) goto failed; Py_XDECREF(tmp); tmp = NULL; -- cgit v1.2.1 From c0be20ca52c183bdf84ec1bafe5ede1fc95e38e9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 9 Aug 2011 16:15:04 -0500 Subject: add a AST validator (closes #12575) --- Python/ast.c | 486 ++++++++++++++++++++++++++++++++++++++++++++++++++- Python/bltinmodule.c | 4 + 2 files changed, 486 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 0d4d9ee9ea..14500eed8d 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1,19 +1,497 @@ /* * This file includes functions to transform a concrete syntax tree (CST) to - * an abstract syntax tree (AST). The main function is PyAST_FromNode(). + * an abstract syntax tree (AST). The main function is PyAST_FromNode(). * */ #include "Python.h" #include "Python-ast.h" -#include "grammar.h" #include "node.h" #include "ast.h" #include "token.h" -#include "parsetok.h" -#include "graminit.h" #include +static int validate_stmts(asdl_seq *); +static int validate_exprs(asdl_seq *, expr_context_ty, int); +static int validate_nonempty_seq(asdl_seq *, const char *, const char *); +static int validate_stmt(stmt_ty); +static int validate_expr(expr_ty, expr_context_ty); + +static int +validate_comprehension(asdl_seq *gens) +{ + int i; + if (!asdl_seq_LEN(gens)) { + PyErr_SetString(PyExc_ValueError, "comprehension with no generators"); + return 0; + } + for (i = 0; i < asdl_seq_LEN(gens); i++) { + comprehension_ty comp = asdl_seq_GET(gens, i); + if (!validate_expr(comp->target, Store) || + !validate_expr(comp->iter, Load) || + !validate_exprs(comp->ifs, Load, 0)) + return 0; + } + return 1; +} + +static int +validate_slice(slice_ty slice) +{ + switch (slice->kind) { + case Slice_kind: + return (!slice->v.Slice.lower || validate_expr(slice->v.Slice.lower, Load)) && + (!slice->v.Slice.upper || validate_expr(slice->v.Slice.upper, Load)) && + (!slice->v.Slice.step || validate_expr(slice->v.Slice.step, Load)); + case ExtSlice_kind: { + int i; + if (!validate_nonempty_seq(slice->v.ExtSlice.dims, "dims", "ExtSlice")) + return 0; + for (i = 0; i < asdl_seq_LEN(slice->v.ExtSlice.dims); i++) + if (!validate_slice(asdl_seq_GET(slice->v.ExtSlice.dims, i))) + return 0; + return 1; + } + case Index_kind: + return validate_expr(slice->v.Index.value, Load); + default: + PyErr_SetString(PyExc_SystemError, "unknown slice node"); + return 0; + } +} + +static int +validate_keywords(asdl_seq *keywords) +{ + int i; + for (i = 0; i < asdl_seq_LEN(keywords); i++) + if (!validate_expr(((keyword_ty)asdl_seq_GET(keywords, i))->value, Load)) + return 0; + return 1; +} + +static int +validate_args(asdl_seq *args) +{ + int i; + for (i = 0; i < asdl_seq_LEN(args); i++) { + arg_ty arg = asdl_seq_GET(args, i); + if (arg->annotation && !validate_expr(arg->annotation, Load)) + return 0; + } + return 1; +} + +static const char * +expr_context_name(expr_context_ty ctx) +{ + switch (ctx) { + case Load: + return "Load"; + case Store: + return "Store"; + case Del: + return "Del"; + case AugLoad: + return "AugLoad"; + case AugStore: + return "AugStore"; + case Param: + return "Param"; + default: + assert(0); + return "(unknown)"; + } +} + +static int +validate_arguments(arguments_ty args) +{ + if (!validate_args(args->args)) + return 0; + if (args->varargannotation) { + if (!args->vararg) { + PyErr_SetString(PyExc_ValueError, "varargannotation but no vararg on arguments"); + return 0; + } + if (!validate_expr(args->varargannotation, Load)) + return 0; + } + if (!validate_args(args->kwonlyargs)) + return 0; + if (args->kwargannotation) { + if (!args->kwarg) { + PyErr_SetString(PyExc_ValueError, "kwargannotation but no kwarg on arguments"); + return 0; + } + if (!validate_expr(args->kwargannotation, Load)) + return 0; + } + if (asdl_seq_LEN(args->defaults) > asdl_seq_LEN(args->args)) { + PyErr_SetString(PyExc_ValueError, "more positional defaults than args on arguments"); + return 0; + } + if (asdl_seq_LEN(args->kw_defaults) != asdl_seq_LEN(args->kwonlyargs)) { + PyErr_SetString(PyExc_ValueError, "length of kwonlyargs is not the same as " + "kw_defaults on arguments"); + return 0; + } + return validate_exprs(args->defaults, Load, 0) && validate_exprs(args->kw_defaults, Load, 1); +} + +static int +validate_expr(expr_ty exp, expr_context_ty ctx) +{ + int check_ctx = 1; + expr_context_ty actual_ctx; + + /* First check expression context. */ + switch (exp->kind) { + case Attribute_kind: + actual_ctx = exp->v.Attribute.ctx; + break; + case Subscript_kind: + actual_ctx = exp->v.Subscript.ctx; + break; + case Starred_kind: + actual_ctx = exp->v.Starred.ctx; + break; + case Name_kind: + actual_ctx = exp->v.Name.ctx; + break; + case List_kind: + actual_ctx = exp->v.List.ctx; + break; + case Tuple_kind: + actual_ctx = exp->v.Tuple.ctx; + break; + default: + if (ctx != Load) { + PyErr_Format(PyExc_ValueError, "expression which can't be " + "assigned to in %s context", expr_context_name(ctx)); + return 0; + } + check_ctx = 0; + } + if (check_ctx && actual_ctx != ctx) { + PyErr_Format(PyExc_ValueError, "expression must have %s context but has %s instead", + expr_context_name(ctx), expr_context_name(actual_ctx)); + return 0; + } + + /* Now validate expression. */ + switch (exp->kind) { + case BoolOp_kind: + if (asdl_seq_LEN(exp->v.BoolOp.values) < 2) { + PyErr_SetString(PyExc_ValueError, "BoolOp with less than 2 values"); + return 0; + } + return validate_exprs(exp->v.BoolOp.values, Load, 0); + case BinOp_kind: + return validate_expr(exp->v.BinOp.left, Load) && + validate_expr(exp->v.BinOp.right, Load); + case UnaryOp_kind: + return validate_expr(exp->v.UnaryOp.operand, Load); + case Lambda_kind: + return validate_arguments(exp->v.Lambda.args) && + validate_expr(exp->v.Lambda.body, Load); + case IfExp_kind: + return validate_expr(exp->v.IfExp.test, Load) && + validate_expr(exp->v.IfExp.body, Load) && + validate_expr(exp->v.IfExp.orelse, Load); + case Dict_kind: + if (asdl_seq_LEN(exp->v.Dict.keys) != asdl_seq_LEN(exp->v.Dict.values)) { + PyErr_SetString(PyExc_ValueError, + "Dict doesn't have the same number of keys as values"); + return 0; + } + return validate_exprs(exp->v.Dict.keys, Load, 0) && + validate_exprs(exp->v.Dict.values, Load, 0); + case Set_kind: + return validate_exprs(exp->v.Set.elts, Load, 0); +#define COMP(NAME) \ + case NAME ## _kind: \ + return validate_comprehension(exp->v.NAME.generators) && \ + validate_expr(exp->v.NAME.elt, Load); + COMP(ListComp) + COMP(SetComp) + COMP(GeneratorExp) +#undef COMP + case DictComp_kind: + return validate_comprehension(exp->v.DictComp.generators) && + validate_expr(exp->v.DictComp.key, Load) && + validate_expr(exp->v.DictComp.value, Load); + case Yield_kind: + return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load); + case Compare_kind: + if (!asdl_seq_LEN(exp->v.Compare.comparators)) { + PyErr_SetString(PyExc_ValueError, "Compare with no comparators"); + return 0; + } + if (asdl_seq_LEN(exp->v.Compare.comparators) != + asdl_seq_LEN(exp->v.Compare.ops)) { + PyErr_SetString(PyExc_ValueError, "Compare has a different number " + "of comparators and operands"); + return 0; + } + return validate_exprs(exp->v.Compare.comparators, Load, 0) && + validate_expr(exp->v.Compare.left, Load); + case Call_kind: + return validate_expr(exp->v.Call.func, Load) && + validate_exprs(exp->v.Call.args, Load, 0) && + validate_keywords(exp->v.Call.keywords) && + (!exp->v.Call.starargs || validate_expr(exp->v.Call.starargs, Load)) && + (!exp->v.Call.kwargs || validate_expr(exp->v.Call.kwargs, Load)); + case Num_kind: { + PyObject *n = exp->v.Num.n; + if (!PyLong_CheckExact(n) && !PyFloat_CheckExact(n) && + !PyComplex_CheckExact(n)) { + PyErr_SetString(PyExc_TypeError, "non-numeric type in Num"); + return 0; + } + return 1; + } + case Str_kind: { + PyObject *s = exp->v.Str.s; + if (!PyUnicode_CheckExact(s)) { + PyErr_SetString(PyExc_TypeError, "non-string type in Str"); + return 0; + } + return 1; + } + case Bytes_kind: { + PyObject *b = exp->v.Bytes.s; + if (!PyBytes_CheckExact(b)) { + PyErr_SetString(PyExc_TypeError, "non-bytes type in Bytes"); + return 0; + } + return 1; + } + case Attribute_kind: + return validate_expr(exp->v.Attribute.value, Load); + case Subscript_kind: + return validate_slice(exp->v.Subscript.slice) && + validate_expr(exp->v.Subscript.value, Load); + case Starred_kind: + return validate_expr(exp->v.Starred.value, ctx); + case List_kind: + return validate_exprs(exp->v.List.elts, ctx, 0); + case Tuple_kind: + return validate_exprs(exp->v.Tuple.elts, ctx, 0); + /* These last cases don't have any checking. */ + case Name_kind: + case Ellipsis_kind: + return 1; + default: + PyErr_SetString(PyExc_SystemError, "unexpected expression"); + return 0; + } +} + +static int +validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner) +{ + if (asdl_seq_LEN(seq)) + return 1; + PyErr_Format(PyExc_ValueError, "empty %s on %s", what, owner); + return 0; +} + +static int +validate_assignlist(asdl_seq *targets, expr_context_ty ctx) +{ + return validate_nonempty_seq(targets, "targets", ctx == Del ? "Delete" : "Assign") && + validate_exprs(targets, ctx, 0); +} + +static int +validate_body(asdl_seq *body, const char *owner) +{ + return validate_nonempty_seq(body, "body", owner) && validate_stmts(body); +} + +static int +validate_stmt(stmt_ty stmt) +{ + int i; + switch (stmt->kind) { + case FunctionDef_kind: + return validate_body(stmt->v.FunctionDef.body, "FunctionDef") && + validate_arguments(stmt->v.FunctionDef.args) && + validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) && + (!stmt->v.FunctionDef.returns || + validate_expr(stmt->v.FunctionDef.returns, Load)); + case ClassDef_kind: + return validate_body(stmt->v.ClassDef.body, "ClassDef") && + validate_exprs(stmt->v.ClassDef.bases, Load, 0) && + validate_keywords(stmt->v.ClassDef.keywords) && + validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0) && + (!stmt->v.ClassDef.starargs || validate_expr(stmt->v.ClassDef.starargs, Load)) && + (!stmt->v.ClassDef.kwargs || validate_expr(stmt->v.ClassDef.kwargs, Load)); + case Return_kind: + return !stmt->v.Return.value || validate_expr(stmt->v.Return.value, Load); + case Delete_kind: + return validate_assignlist(stmt->v.Delete.targets, Del); + case Assign_kind: + return validate_assignlist(stmt->v.Assign.targets, Store) && + validate_expr(stmt->v.Assign.value, Load); + case AugAssign_kind: + return validate_expr(stmt->v.AugAssign.target, Store) && + validate_expr(stmt->v.AugAssign.value, Load); + case For_kind: + return validate_expr(stmt->v.For.target, Store) && + validate_expr(stmt->v.For.iter, Load) && + validate_body(stmt->v.For.body, "For") && + validate_stmts(stmt->v.For.orelse); + case While_kind: + return validate_expr(stmt->v.While.test, Load) && + validate_body(stmt->v.While.body, "While") && + validate_stmts(stmt->v.While.orelse); + case If_kind: + return validate_expr(stmt->v.If.test, Load) && + validate_body(stmt->v.If.body, "If") && + validate_stmts(stmt->v.If.orelse); + case With_kind: + if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) + return 0; + for (i = 0; i < asdl_seq_LEN(stmt->v.With.items); i++) { + withitem_ty item = asdl_seq_GET(stmt->v.With.items, i); + if (!validate_expr(item->context_expr, Load) || + (item->optional_vars && !validate_expr(item->optional_vars, Store))) + return 0; + } + return validate_body(stmt->v.With.body, "With"); + case Raise_kind: + if (stmt->v.Raise.exc) { + return validate_expr(stmt->v.Raise.exc, Load) && + (!stmt->v.Raise.cause || validate_expr(stmt->v.Raise.cause, Load)); + } + if (stmt->v.Raise.cause) { + PyErr_SetString(PyExc_ValueError, "Raise with cause but no exception"); + return 0; + } + return 1; + case Try_kind: + if (!validate_body(stmt->v.Try.body, "Try")) + return 0; + if (!asdl_seq_LEN(stmt->v.Try.handlers) && + !asdl_seq_LEN(stmt->v.Try.finalbody)) { + PyErr_SetString(PyExc_ValueError, "Try has neither except handlers nor finalbody"); + return 0; + } + if (!asdl_seq_LEN(stmt->v.Try.handlers) && + asdl_seq_LEN(stmt->v.Try.orelse)) { + PyErr_SetString(PyExc_ValueError, "Try has orelse but no except handlers"); + return 0; + } + for (i = 0; i < asdl_seq_LEN(stmt->v.Try.handlers); i++) { + excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); + if ((handler->v.ExceptHandler.type && + !validate_expr(handler->v.ExceptHandler.type, Load)) || + !validate_body(handler->v.ExceptHandler.body, "ExceptHandler")) + return 0; + } + return (!asdl_seq_LEN(stmt->v.Try.finalbody) || + validate_stmts(stmt->v.Try.finalbody)) && + (!asdl_seq_LEN(stmt->v.Try.orelse) || + validate_stmts(stmt->v.Try.orelse)); + case Assert_kind: + return validate_expr(stmt->v.Assert.test, Load) && + (!stmt->v.Assert.msg || validate_expr(stmt->v.Assert.msg, Load)); + case Import_kind: + return validate_nonempty_seq(stmt->v.Import.names, "names", "Import"); + case ImportFrom_kind: + if (stmt->v.ImportFrom.level < -1) { + PyErr_SetString(PyExc_ValueError, "ImportFrom level less than -1"); + return 0; + } + return validate_nonempty_seq(stmt->v.ImportFrom.names, "names", "ImportFrom"); + case Global_kind: + return validate_nonempty_seq(stmt->v.Global.names, "names", "Global"); + case Nonlocal_kind: + return validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal"); + case Expr_kind: + return validate_expr(stmt->v.Expr.value, Load); + case Pass_kind: + case Break_kind: + case Continue_kind: + return 1; + default: + PyErr_SetString(PyExc_SystemError, "unexpected statement"); + return 0; + } +} + +static int +validate_stmts(asdl_seq *seq) +{ + int i; + for (i = 0; i < asdl_seq_LEN(seq); i++) { + stmt_ty stmt = asdl_seq_GET(seq, i); + if (stmt) { + if (!validate_stmt(stmt)) + return 0; + } + else { + PyErr_SetString(PyExc_ValueError, + "None disallowed in statement list"); + return 0; + } + } + return 1; +} + +static int +validate_exprs(asdl_seq *exprs, expr_context_ty ctx, int null_ok) +{ + int i; + for (i = 0; i < asdl_seq_LEN(exprs); i++) { + expr_ty expr = asdl_seq_GET(exprs, i); + if (expr) { + if (!validate_expr(expr, ctx)) + return 0; + } + else if (!null_ok) { + PyErr_SetString(PyExc_ValueError, + "None disallowed in expression list"); + return 0; + } + + } + return 1; +} + +int +PyAST_Validate(mod_ty mod) +{ + int res = 0; + + switch (mod->kind) { + case Module_kind: + res = validate_stmts(mod->v.Module.body); + break; + case Interactive_kind: + res = validate_stmts(mod->v.Interactive.body); + break; + case Expression_kind: + res = validate_expr(mod->v.Expression.body, Load); + break; + case Suite_kind: + PyErr_SetString(PyExc_ValueError, "Suite is not valid in the CPython compiler"); + break; + default: + PyErr_SetString(PyExc_SystemError, "impossible module node"); + res = 0; + break; + } + return res; +} + +/* This is down here, so defines like "test" don't intefere with access AST above. */ +#include "grammar.h" +#include "parsetok.h" +#include "graminit.h" + /* Data structure used internally */ struct compiling { char *c_encoding; /* source encoding */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 152210b30b..94b2798fee 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -604,6 +604,10 @@ builtin_compile(PyObject *self, PyObject *args, PyObject *kwds) PyArena_Free(arena); goto error; } + if (!PyAST_Validate(mod)) { + PyArena_Free(arena); + goto error; + } result = (PyObject*)PyAST_CompileEx(mod, filename, &cf, optimize, arena); PyArena_Free(arena); -- cgit v1.2.1 From 27a1145ea78bbe848a026d11fe972d873aecb86e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 12 Aug 2011 23:10:50 -0500 Subject: include header with PyAST_Validate --- Python/bltinmodule.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 94b2798fee..9de8ca036f 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -6,6 +6,9 @@ #include "node.h" #include "code.h" +#include "asdl.h" +#include "ast.h" + #include #ifdef HAVE_LANGINFO_H -- cgit v1.2.1 From 9ce343f33c35b14fe616a15cea33f8f84ccbff85 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Sep 2011 19:50:01 +0200 Subject: import.c: remove now useless arbitrary limit --- Python/import.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 7902721a92..adfd2cc5df 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1980,12 +1980,6 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, if (p_loader != NULL) *p_loader = NULL; - if (PyUnicode_GET_SIZE(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; -- cgit v1.2.1 From 4e7a29bf47bd58f536731ef33916b6518898760f Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Wed, 21 Sep 2011 19:08:39 +0200 Subject: Issue #13002: Fix Visual Studio warning (not enough actual parameters). --- Python/peephole.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/peephole.c b/Python/peephole.c index 781498ecf2..705622f18e 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -66,7 +66,7 @@ const_stack_top = -1; \ } while(0) -#define CONST_STACK_TOP(x) \ +#define CONST_STACK_TOP() \ const_stack[const_stack_top] #define CONST_STACK_LASTN(i) \ -- cgit v1.2.1 From d1d013c01c268d869597b35cbcd8b5d7c5baf2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Wed, 28 Sep 2011 07:41:54 +0200 Subject: Implement PEP 393. --- Python/_warnings.c | 16 +- Python/ast.c | 61 +- Python/bltinmodule.c | 26 +- Python/ceval.c | 17 +- Python/codecs.c | 44 +- Python/compile.c | 89 +-- Python/errors.c | 4 +- Python/formatter_unicode.c | 1445 +++++++++++++++++++++++++++++++++++++++++++- Python/getargs.c | 46 +- Python/import.c | 335 +++++----- Python/marshal.c | 4 +- Python/peephole.c | 18 - Python/symtable.c | 8 +- Python/traceback.c | 61 +- 14 files changed, 1824 insertions(+), 350 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index f8a7175f92..2bcca91fa6 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -498,17 +498,19 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *filename = PyDict_GetItemString(globals, "__file__"); if (*filename != NULL && PyUnicode_Check(*filename)) { Py_ssize_t len = PyUnicode_GetSize(*filename); - Py_UNICODE *unicode = PyUnicode_AS_UNICODE(*filename); + int kind = PyUnicode_KIND(*filename); + void *data = PyUnicode_DATA(*filename); /* if filename.lower().endswith((".pyc", ".pyo")): */ if (len >= 4 && - unicode[len-4] == '.' && - Py_UNICODE_TOLOWER(unicode[len-3]) == 'p' && - Py_UNICODE_TOLOWER(unicode[len-2]) == 'y' && - (Py_UNICODE_TOLOWER(unicode[len-1]) == 'c' || - Py_UNICODE_TOLOWER(unicode[len-1]) == 'o')) + PyUnicode_READ(kind, data, len-4) == '.' && + Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-3)) == 'p' && + Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-2)) == 'y' && + (Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'c' || + Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'o')) { - *filename = PyUnicode_FromUnicode(unicode, len-1); + *filename = PyUnicode_Substring(*filename, 0, + PyUnicode_GET_LENGTH(*filename)-1); if (*filename == NULL) goto handle_error; } diff --git a/Python/ast.c b/Python/ast.c index 14500eed8d..a52fd093e6 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -528,26 +528,21 @@ static identifier new_identifier(const char* n, PyArena *arena) { PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); - Py_UNICODE *u; - if (!id) + if (!id || PyUnicode_READY(id) == -1) return NULL; - u = PyUnicode_AS_UNICODE(id); /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ - for (; *u; u++) { - if (*u >= 128) { - PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); - PyObject *id2; - if (!m) - return NULL; - id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id); - Py_DECREF(m); - if (!id2) - return NULL; - Py_DECREF(id); - id = id2; - break; - } + if (PyUnicode_MAX_CHAR_VALUE((PyUnicodeObject *)id) >= 128) { + PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); + PyObject *id2; + if (!m) + return NULL; + id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id); + Py_DECREF(m); + if (!id2) + return NULL; + Py_DECREF(id); + id = id2; } PyUnicode_InternInPlace(&id); PyArena_AddPyObject(arena, id); @@ -3660,20 +3655,14 @@ parsenumber(struct compiling *c, const char *s) } static PyObject * -decode_utf8(struct compiling *c, const char **sPtr, const char *end, char* encoding) +decode_utf8(struct compiling *c, const char **sPtr, const char *end) { - PyObject *u, *v; char *s, *t; t = s = (char *)*sPtr; /* while (s < end && *s != '\\') s++; */ /* inefficient for u".." */ while (s < end && (*s & 0x80)) s++; *sPtr = s; - u = PyUnicode_DecodeUTF8(t, s - t, NULL); - if (u == NULL) - return NULL; - v = PyUnicode_AsEncodedString(u, encoding, NULL); - Py_DECREF(u); - return v; + return PyUnicode_DecodeUTF8(t, s - t, NULL); } static PyObject * @@ -3707,22 +3696,20 @@ decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, cons } if (*s & 0x80) { /* XXX inefficient */ PyObject *w; - char *r; - Py_ssize_t rn, i; - w = decode_utf8(c, &s, end, "utf-32-be"); + int kind; + void *data; + Py_ssize_t len, i; + w = decode_utf8(c, &s, end); if (w == NULL) { Py_DECREF(u); return NULL; } - r = PyBytes_AS_STRING(w); - rn = Py_SIZE(w); - assert(rn % 4 == 0); - for (i = 0; i < rn; i += 4) { - sprintf(p, "\\U%02x%02x%02x%02x", - r[i + 0] & 0xFF, - r[i + 1] & 0xFF, - r[i + 2] & 0xFF, - r[i + 3] & 0xFF); + kind = PyUnicode_KIND(w); + data = PyUnicode_DATA(w); + len = PyUnicode_GET_LENGTH(w); + for (i = 0; i < len; i++) { + Py_UCS4 chr = PyUnicode_READ(kind, data, i); + sprintf(p, "\\U%08x", chr); p += 10; } /* Should be impossible to overflow */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9de8ca036f..04f5231891 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -508,8 +508,8 @@ 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); - if (cmd == NULL) + str = PyUnicode_AsUTF8AndSize(cmd, &size); + if (str == NULL) return NULL; } else if (!PyObject_CheckReadBuffer(cmd)) { @@ -518,9 +518,10 @@ source_as_string(PyObject *cmd, char *funcname, char *what, PyCompilerFlags *cf) funcname, what); return NULL; } - if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { + else if (PyObject_AsReadBuffer(cmd, (const void **)&str, &size) < 0) { return NULL; } + if (strlen(str) != size) { PyErr_SetString(PyExc_TypeError, "source code string cannot contain null bytes"); @@ -1395,24 +1396,13 @@ builtin_ord(PyObject *self, PyObject* obj) } } else if (PyUnicode_Check(obj)) { - size = PyUnicode_GET_SIZE(obj); + if (PyUnicode_READY(obj) == -1) + return NULL; + size = PyUnicode_GET_LENGTH(obj); if (size == 1) { - ord = (long)*PyUnicode_AS_UNICODE(obj); + ord = (long)PyUnicode_READ_CHAR(obj, 0); return PyLong_FromLong(ord); } -#ifndef Py_UNICODE_WIDE - if (size == 2) { - /* Decode a valid surrogate pair */ - int c0 = PyUnicode_AS_UNICODE(obj)[0]; - int c1 = PyUnicode_AS_UNICODE(obj)[1]; - if (0xD800 <= c0 && c0 <= 0xDBFF && - 0xDC00 <= c1 && c1 <= 0xDFFF) { - ord = ((((c0 & 0x03FF) << 10) | (c1 & 0x03FF)) + - 0x00010000); - return PyLong_FromLong(ord); - } - } -#endif } else if (PyByteArray_Check(obj)) { /* XXX Hopefully this is temporary */ diff --git a/Python/ceval.c b/Python/ceval.c index 1c9153e276..0a346f4179 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2054,7 +2054,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Inline the PyDict_GetItem() calls. WARNING: this is an extreme speed hack. Do not try this at home. */ - Py_hash_t hash = ((PyUnicodeObject *)w)->hash; + Py_hash_t hash = ((PyASCIIObject *)w)->hash; if (hash != -1) { PyDictObject *d; PyDictEntry *e; @@ -4456,7 +4456,8 @@ import_all_from(PyObject *locals, PyObject *v) } if (skip_leading_underscores && PyUnicode_Check(name) && - PyUnicode_AS_UNICODE(name)[0] == '_') + PyUnicode_READY(name) != -1 && + PyUnicode_READ_CHAR(name, 0) == '_') { Py_DECREF(name); continue; @@ -4520,6 +4521,14 @@ unicode_concatenate(PyObject *v, PyObject *w, { /* This function implements 'variable += expr' when both arguments are (Unicode) strings. */ + + w = PyUnicode_Concat(v, w); + Py_DECREF(v); + return w; + + /* XXX: This optimization is currently disabled as unicode objects in the + new flexible representation are not in-place resizable anymore. */ +#if 0 Py_ssize_t v_len = PyUnicode_GET_SIZE(v); Py_ssize_t w_len = PyUnicode_GET_SIZE(w); Py_ssize_t new_len = v_len + w_len; @@ -4570,7 +4579,8 @@ unicode_concatenate(PyObject *v, PyObject *w, } } - if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { + if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v) && + !PyUnicode_IS_COMPACT((PyUnicodeObject *)v)) { /* Now we own the last reference to 'v', so we can resize it * in-place. */ @@ -4594,6 +4604,7 @@ unicode_concatenate(PyObject *v, PyObject *w, Py_DECREF(v); return w; } +#endif } #ifdef DYNAMIC_EXECUTION_PROFILE diff --git a/Python/codecs.c b/Python/codecs.c index 1a3e45774c..be2e8334c6 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -513,27 +513,25 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) PyObject *PyCodec_ReplaceErrors(PyObject *exc) { - PyObject *restuple; - Py_ssize_t start; - Py_ssize_t end; - Py_ssize_t i; + Py_ssize_t start, end, i, len; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { PyObject *res; - Py_UNICODE *p; + int kind; + void *data; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; - res = PyUnicode_FromUnicode(NULL, end-start); + len = end - start; + res = PyUnicode_New(len, '?'); if (res == NULL) return NULL; - for (p = PyUnicode_AS_UNICODE(res), i = start; - i maxchar) + maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj); + + result = PyUnicode_New(1 + nlen + plen, maxchar); + if (!result) return 0; - /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ - buffer = PyUnicode_AS_UNICODE(ident); - buffer[0] = '_'; - Py_UNICODE_strncpy(buffer+1, p, plen); - Py_UNICODE_strcpy(buffer+1+plen, name); - return ident; + /* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */ + PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_'); + PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen); + PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen); + return result; } static int @@ -2085,22 +2091,27 @@ compiler_import_as(struct compiler *c, identifier name, identifier asname) If there is a dot in name, we need to split it and emit a LOAD_ATTR for each name. */ - const Py_UNICODE *src = PyUnicode_AS_UNICODE(name); - const Py_UNICODE *dot = Py_UNICODE_strchr(src, '.'); - if (dot) { + Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, + PyUnicode_GET_LENGTH(name), 1); + if (dot == -2) + return -1; + if (dot != -1) { /* Consume the base module name to get the first attribute */ - src = dot + 1; - while (dot) { - /* NB src is only defined when dot != NULL */ + Py_ssize_t pos = dot + 1; + while (dot != -1) { PyObject *attr; - dot = Py_UNICODE_strchr(src, '.'); - attr = PyUnicode_FromUnicode(src, - dot ? dot - src : Py_UNICODE_strlen(src)); + dot = PyUnicode_FindChar(name, '.', pos, + PyUnicode_GET_LENGTH(name), 1); + if (dot == -2) + return -1; + attr = PyUnicode_Substring(name, pos, + (dot != -1) ? dot : + PyUnicode_GET_LENGTH(name)); if (!attr) return -1; ADDOP_O(c, LOAD_ATTR, attr, names); Py_DECREF(attr); - src = dot + 1; + pos = dot + 1; } } return compiler_nameop(c, asname, Store); @@ -2139,13 +2150,12 @@ compiler_import(struct compiler *c, stmt_ty s) } else { identifier tmp = alias->name; - const Py_UNICODE *base = PyUnicode_AS_UNICODE(alias->name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) - tmp = PyUnicode_FromUnicode(base, - dot - base); + Py_ssize_t dot = PyUnicode_FindChar( + alias->name, '.', 0, PyUnicode_GET_LENGTH(alias->name), 1); + if (dot != -1) + tmp = PyUnicode_Substring(alias->name, 0, dot); r = compiler_nameop(c, tmp, Store); - if (dot) { + if (dot != -1) { Py_DECREF(tmp); } if (!r) @@ -2208,7 +2218,7 @@ compiler_from_import(struct compiler *c, stmt_ty s) alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name; - if (i == 0 && *PyUnicode_AS_UNICODE(alias->name) == '*') { + if (i == 0 && PyUnicode_READ_CHAR(alias->name, 0) == '*') { assert(n == 1); ADDOP(c, IMPORT_STAR); return 1; @@ -2522,7 +2532,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) } /* XXX Leave assert here, but handle __doc__ and the like better */ - assert(scope || PyUnicode_AS_UNICODE(name)[0] == '_'); + assert(scope || PyUnicode_READ_CHAR(name, 0) == '_'); switch (optype) { case OP_DEREF: @@ -3045,8 +3055,7 @@ expr_constant(struct compiler *c, expr_ty e) return PyObject_IsTrue(e->v.Str.s); case Name_kind: /* optimize away names that can't be reassigned */ - id = PyBytes_AS_STRING( - _PyUnicode_AsDefaultEncodedString(e->v.Name.id)); + id = PyUnicode_AsUTF8(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/errors.c b/Python/errors.c index 5a9a624279..149151ebfa 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -395,7 +395,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) /* remove trailing cr/lf and dots */ while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) s_buf[--len] = L'\0'; - message = PyUnicode_FromUnicode(s_buf, len); + message = PyUnicode_FromWideChar(s_buf, len); } } } @@ -487,7 +487,7 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( /* remove trailing cr/lf and dots */ while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) s_buf[--len] = L'\0'; - message = PyUnicode_FromUnicode(s_buf, len); + message = PyUnicode_FromWideChar(s_buf, len); } if (message == NULL) diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index c350907da1..9fb840b160 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -3,12 +3,1445 @@ of int.__float__, etc., that take and return unicode objects */ #include "Python.h" -#include "../Objects/stringlib/unicodedefs.h" +#include +/* Raises an exception about an unknown presentation type for this + * type. */ -#define FORMAT_STRING _PyUnicode_FormatAdvanced -#define FORMAT_LONG _PyLong_FormatAdvanced -#define FORMAT_FLOAT _PyFloat_FormatAdvanced -#define FORMAT_COMPLEX _PyComplex_FormatAdvanced +static void +unknown_presentation_type(Py_UCS4 presentation_type, + const char* type_name) +{ + /* %c might be out-of-range, hence the two cases. */ + if (presentation_type > 32 && presentation_type < 128) + PyErr_Format(PyExc_ValueError, + "Unknown format code '%c' " + "for object of type '%.200s'", + (char)presentation_type, + type_name); + else + PyErr_Format(PyExc_ValueError, + "Unknown format code '\\x%x' " + "for object of type '%.200s'", + (unsigned int)presentation_type, + type_name); +} -#include "../Objects/stringlib/formatter.h" +static void +invalid_comma_type(Py_UCS4 presentation_type) +{ + if (presentation_type > 32 && presentation_type < 128) + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '%c'.", + (char)presentation_type); + else + PyErr_Format(PyExc_ValueError, + "Cannot specify ',' with '\\x%x'.", + (unsigned int)presentation_type); +} + +/* + get_integer consumes 0 or more decimal digit characters from an + input string, updates *result with the corresponding positive + integer, and returns the number of digits consumed. + + returns -1 on error. +*/ +static int +get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end, + Py_ssize_t *result) +{ + Py_ssize_t accumulator, digitval, oldaccumulator; + int numdigits; + accumulator = numdigits = 0; + for (;;(*pos)++, numdigits++) { + if (*pos >= end) + break; + digitval = Py_UNICODE_TODECIMAL(PyUnicode_READ_CHAR(str, *pos)); + if (digitval < 0) + break; + /* + This trick was copied from old Unicode format code. It's cute, + but would really suck on an old machine with a slow divide + implementation. Fortunately, in the normal case we do not + expect too many digits. + */ + oldaccumulator = accumulator; + accumulator *= 10; + if ((accumulator+10)/10 != oldaccumulator+1) { + PyErr_Format(PyExc_ValueError, + "Too many decimal digits in format string"); + return -1; + } + accumulator += digitval; + } + *result = accumulator; + return numdigits; +} + +/************************************************************************/ +/*********** standard format specifier parsing **************************/ +/************************************************************************/ + +/* returns true if this character is a specifier alignment token */ +Py_LOCAL_INLINE(int) +is_alignment_token(Py_UCS4 c) +{ + switch (c) { + case '<': case '>': case '=': case '^': + return 1; + default: + return 0; + } +} + +/* returns true if this character is a sign element */ +Py_LOCAL_INLINE(int) +is_sign_element(Py_UCS4 c) +{ + switch (c) { + case ' ': case '+': case '-': + return 1; + default: + return 0; + } +} + + +typedef struct { + Py_UCS4 fill_char; + Py_UCS4 align; + int alternate; + Py_UCS4 sign; + Py_ssize_t width; + int thousands_separators; + Py_ssize_t precision; + Py_UCS4 type; +} InternalFormatSpec; + +#if 0 +/* Occassionally useful for debugging. Should normally be commented out. */ +static void +DEBUG_PRINT_FORMAT_SPEC(InternalFormatSpec *format) +{ + printf("internal format spec: fill_char %d\n", format->fill_char); + printf("internal format spec: align %d\n", format->align); + printf("internal format spec: alternate %d\n", format->alternate); + printf("internal format spec: sign %d\n", format->sign); + printf("internal format spec: width %zd\n", format->width); + printf("internal format spec: thousands_separators %d\n", + format->thousands_separators); + printf("internal format spec: precision %zd\n", format->precision); + printf("internal format spec: type %c\n", format->type); + printf("\n"); +} +#endif + + +/* + ptr points to the start of the format_spec, end points just past its end. + fills in format with the parsed information. + returns 1 on success, 0 on failure. + if failure, sets the exception +*/ +static int +parse_internal_render_format_spec(PyObject *format_spec, + Py_ssize_t start, Py_ssize_t end, + InternalFormatSpec *format, + char default_type, + char default_align) +{ + Py_ssize_t pos = start; + /* end-pos is used throughout this code to specify the length of + the input string */ +#define READ_spec(index) PyUnicode_READ_CHAR(format_spec, index) + + Py_ssize_t consumed; + int align_specified = 0; + + format->fill_char = '\0'; + format->align = default_align; + format->alternate = 0; + format->sign = '\0'; + format->width = -1; + format->thousands_separators = 0; + format->precision = -1; + format->type = default_type; + + /* If the second char is an alignment token, + then parse the fill char */ + if (end-pos >= 2 && is_alignment_token(READ_spec(pos+1))) { + format->align = READ_spec(pos+1); + format->fill_char = READ_spec(pos); + align_specified = 1; + pos += 2; + } + else if (end-pos >= 1 && is_alignment_token(READ_spec(pos))) { + format->align = READ_spec(pos); + align_specified = 1; + ++pos; + } + + /* Parse the various sign options */ + if (end-pos >= 1 && is_sign_element(READ_spec(pos))) { + format->sign = READ_spec(pos); + ++pos; + } + + /* If the next character is #, we're in alternate mode. This only + applies to integers. */ + if (end-pos >= 1 && READ_spec(pos) == '#') { + format->alternate = 1; + ++pos; + } + + /* The special case for 0-padding (backwards compat) */ + if (format->fill_char == '\0' && end-pos >= 1 && READ_spec(pos) == '0') { + format->fill_char = '0'; + if (!align_specified) { + format->align = '='; + } + ++pos; + } + + consumed = get_integer(format_spec, &pos, end, &format->width); + if (consumed == -1) + /* Overflow error. Exception already set. */ + return 0; + + /* If consumed is 0, we didn't consume any characters for the + width. In that case, reset the width to -1, because + get_integer() will have set it to zero. -1 is how we record + that the width wasn't specified. */ + if (consumed == 0) + format->width = -1; + + /* Comma signifies add thousands separators */ + if (end-pos && READ_spec(pos) == ',') { + format->thousands_separators = 1; + ++pos; + } + + /* Parse field precision */ + if (end-pos && READ_spec(pos) == '.') { + ++pos; + + consumed = get_integer(format_spec, &pos, end, &format->precision); + if (consumed == -1) + /* Overflow error. Exception already set. */ + return 0; + + /* Not having a precision after a dot is an error. */ + if (consumed == 0) { + PyErr_Format(PyExc_ValueError, + "Format specifier missing precision"); + return 0; + } + + } + + /* Finally, parse the type field. */ + + if (end-pos > 1) { + /* More than one char remain, invalid conversion spec. */ + PyErr_Format(PyExc_ValueError, "Invalid conversion specification"); + return 0; + } + + if (end-pos == 1) { + format->type = READ_spec(pos); + ++pos; + } + + /* Do as much validating as we can, just by looking at the format + specifier. Do not take into account what type of formatting + we're doing (int, float, string). */ + + if (format->thousands_separators) { + switch (format->type) { + case 'd': + case 'e': + case 'f': + case 'g': + case 'E': + case 'G': + case '%': + case 'F': + case '\0': + /* These are allowed. See PEP 378.*/ + break; + default: + invalid_comma_type(format->type); + return 0; + } + } + + if (format->fill_char > 127 || format->align > 127 || + format->sign > 127) { + PyErr_SetString(PyExc_ValueError, "fill character too large"); + return 0; + } + + return 1; +} + +/* Calculate the padding needed. */ +static void +calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align, + Py_ssize_t *n_lpadding, Py_ssize_t *n_rpadding, + Py_ssize_t *n_total) +{ + if (width >= 0) { + if (nchars > width) + *n_total = nchars; + else + *n_total = width; + } + else { + /* not specified, use all of the chars and no more */ + *n_total = nchars; + } + + /* Figure out how much leading space we need, based on the + aligning */ + if (align == '>') + *n_lpadding = *n_total - nchars; + else if (align == '^') + *n_lpadding = (*n_total - nchars) / 2; + else if (align == '<' || align == '=') + *n_lpadding = 0; + else { + /* We should never have an unspecified alignment. */ + *n_lpadding = 0; + assert(0); + } + + *n_rpadding = *n_total - nchars - *n_lpadding; +} + +static void +unicode_fill(PyObject *str, Py_ssize_t start, Py_ssize_t end, Py_UCS4 ch) +{ + int kind = PyUnicode_KIND(str); + void *data = PyUnicode_DATA(str); + while (start < end) + PyUnicode_WRITE(kind, data, start++, ch); +} + +/* Do the padding, and return a pointer to where the caller-supplied + content goes. */ +static Py_ssize_t +fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars, + Py_UCS4 fill_char, Py_ssize_t n_lpadding, + Py_ssize_t n_rpadding) +{ + /* Pad on left. */ + if (n_lpadding) + unicode_fill(s, start, start + n_lpadding, fill_char); + + /* Pad on right. */ + if (n_rpadding) + unicode_fill(s, start + nchars + n_lpadding, + start + nchars + n_lpadding + n_rpadding, fill_char); + + /* Pointer to the user content. */ + return start + n_lpadding; +} + +/************************************************************************/ +/*********** common routines for numeric formatting *********************/ +/************************************************************************/ + +/* Locale type codes. */ +#define LT_CURRENT_LOCALE 0 +#define LT_DEFAULT_LOCALE 1 +#define LT_NO_LOCALE 2 + +/* Locale info needed for formatting integers and the part of floats + before and including the decimal. Note that locales only support + 8-bit chars, not unicode. */ +typedef struct { + char *decimal_point; + char *thousands_sep; + char *grouping; +} LocaleInfo; + +/* describes the layout for an integer, see the comment in + calc_number_widths() for details */ +typedef struct { + Py_ssize_t n_lpadding; + Py_ssize_t n_prefix; + Py_ssize_t n_spadding; + Py_ssize_t n_rpadding; + char sign; + Py_ssize_t n_sign; /* number of digits needed for sign (0/1) */ + Py_ssize_t n_grouped_digits; /* Space taken up by the digits, including + any grouping chars. */ + Py_ssize_t n_decimal; /* 0 if only an integer */ + Py_ssize_t n_remainder; /* Digits in decimal and/or exponent part, + excluding the decimal itself, if + present. */ + + /* These 2 are not the widths of fields, but are needed by + STRINGLIB_GROUPING. */ + Py_ssize_t n_digits; /* The number of digits before a decimal + or exponent. */ + Py_ssize_t n_min_width; /* The min_width we used when we computed + the n_grouped_digits width. */ +} NumberFieldWidths; + + +/* Given a number of the form: + digits[remainder] + where ptr points to the start and end points to the end, find where + the integer part ends. This could be a decimal, an exponent, both, + or neither. + If a decimal point is present, set *has_decimal and increment + remainder beyond it. + Results are undefined (but shouldn't crash) for improperly + formatted strings. +*/ +static void +parse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end, + Py_ssize_t *n_remainder, int *has_decimal) +{ + Py_ssize_t remainder; + + while (posn_digits = n_end - n_start - n_remainder - (has_decimal?1:0); + spec->n_lpadding = 0; + spec->n_prefix = n_prefix; + spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0; + spec->n_remainder = n_remainder; + spec->n_spadding = 0; + spec->n_rpadding = 0; + spec->sign = '\0'; + spec->n_sign = 0; + + /* the output will look like: + | | + | | + | | + + sign is computed from format->sign and the actual + sign of the number + + prefix is given (it's for the '0x' prefix) + + digits is already known + + the total width is either given, or computed from the + actual digits + + only one of lpadding, spadding, and rpadding can be non-zero, + and it's calculated from the width and other fields + */ + + /* compute the various parts we're going to write */ + switch (format->sign) { + case '+': + /* always put a + or - */ + spec->n_sign = 1; + spec->sign = (sign_char == '-' ? '-' : '+'); + break; + case ' ': + spec->n_sign = 1; + spec->sign = (sign_char == '-' ? '-' : ' '); + break; + default: + /* Not specified, or the default (-) */ + if (sign_char == '-') { + spec->n_sign = 1; + spec->sign = '-'; + } + } + + /* The number of chars used for non-digits and non-padding. */ + n_non_digit_non_padding = spec->n_sign + spec->n_prefix + spec->n_decimal + + spec->n_remainder; + + /* min_width can go negative, that's okay. format->width == -1 means + we don't care. */ + if (format->fill_char == '0' && format->align == '=') + spec->n_min_width = format->width - n_non_digit_non_padding; + else + spec->n_min_width = 0; + + if (spec->n_digits == 0) + /* This case only occurs when using 'c' formatting, we need + to special case it because the grouping code always wants + to have at least one character. */ + spec->n_grouped_digits = 0; + else + spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping( + PyUnicode_1BYTE_KIND, NULL, 0, NULL, + spec->n_digits, spec->n_min_width, + locale->grouping, locale->thousands_sep); + + /* Given the desired width and the total of digit and non-digit + space we consume, see if we need any padding. format->width can + be negative (meaning no padding), but this code still works in + that case. */ + n_padding = format->width - + (n_non_digit_non_padding + spec->n_grouped_digits); + if (n_padding > 0) { + /* Some padding is needed. Determine if it's left, space, or right. */ + switch (format->align) { + case '<': + spec->n_rpadding = n_padding; + break; + case '^': + spec->n_lpadding = n_padding / 2; + spec->n_rpadding = n_padding - spec->n_lpadding; + break; + case '=': + spec->n_spadding = n_padding; + break; + case '>': + spec->n_lpadding = n_padding; + break; + default: + /* Shouldn't get here, but treat it as '>' */ + spec->n_lpadding = n_padding; + assert(0); + break; + } + } + return spec->n_lpadding + spec->n_sign + spec->n_prefix + + spec->n_spadding + spec->n_grouped_digits + spec->n_decimal + + spec->n_remainder + spec->n_rpadding; +} + +/* Fill in the digit parts of a numbers's string representation, + as determined in calc_number_widths(). + No error checking, since we know the buffer is the correct size. */ +static void +fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, + PyObject *digits, Py_ssize_t d_start, Py_ssize_t d_end, + PyObject *prefix, Py_ssize_t p_start, Py_UCS4 fill_char, + LocaleInfo *locale, int toupper) +{ + /* Used to keep track of digits, decimal, and remainder. */ + Py_ssize_t d_pos = d_start; + unsigned int kind = PyUnicode_KIND(out); + void *data = PyUnicode_DATA(out); + +#ifndef NDEBUG + Py_ssize_t r; +#endif + + if (spec->n_lpadding) { + unicode_fill(out, pos, pos + spec->n_lpadding, fill_char); + pos += spec->n_lpadding; + } + if (spec->n_sign == 1) { + PyUnicode_WRITE(kind, data, pos++, spec->sign); + } + if (spec->n_prefix) { + PyUnicode_CopyCharacters(out, pos, prefix, p_start, spec->n_prefix); + if (toupper) { + Py_ssize_t t; + /* XXX if the upper-case prefix is wider than the target + buffer, the caller should have allocated a wider string, + but currently doesn't. */ + for (t = 0; t < spec->n_prefix; ++t) + PyUnicode_WRITE(kind, data, pos + t, + Py_UNICODE_TOUPPER( + PyUnicode_READ(kind, data, pos + t))); + } + pos += spec->n_prefix; + } + if (spec->n_spadding) { + unicode_fill(out, pos, pos + spec->n_spadding, fill_char); + pos += spec->n_spadding; + } + + /* Only for type 'c' special case, it has no digits. */ + if (spec->n_digits != 0) { + /* Fill the digits with InsertThousandsGrouping. */ + char *pdigits = PyUnicode_DATA(digits); + if (PyUnicode_KIND(digits) < kind) { + pdigits = _PyUnicode_AsKind(digits, kind); + if (pdigits == NULL) { + /* XXX report exception */ + Py_FatalError("out of memory"); + return; + } + } +#ifndef NDEBUG + r = +#endif + _PyUnicode_InsertThousandsGrouping( + kind, + (char*)data + PyUnicode_KIND_SIZE(kind, pos), + spec->n_grouped_digits, + pdigits + PyUnicode_KIND_SIZE(kind, d_pos), + spec->n_digits, spec->n_min_width, + locale->grouping, locale->thousands_sep); +#ifndef NDEBUG + assert(r == spec->n_grouped_digits); +#endif + if (PyUnicode_KIND(digits) < kind) + PyMem_Free(pdigits); + d_pos += spec->n_digits; + } + if (toupper) { + Py_ssize_t t; + for (t = 0; t < spec->n_grouped_digits; ++t) + PyUnicode_WRITE(kind, data, pos + t, + Py_UNICODE_TOUPPER( + PyUnicode_READ(kind, data, pos + t))); + } + pos += spec->n_grouped_digits; + + if (spec->n_decimal) { + Py_ssize_t t; + for (t = 0; t < spec->n_decimal; ++t) + PyUnicode_WRITE(kind, data, pos + t, + locale->decimal_point[t]); + pos += spec->n_decimal; + d_pos += 1; + } + + if (spec->n_remainder) { + PyUnicode_CopyCharacters(out, pos, digits, d_pos, spec->n_remainder); + pos += spec->n_remainder; + d_pos += spec->n_remainder; + } + + if (spec->n_rpadding) { + unicode_fill(out, pos, pos + spec->n_rpadding, fill_char); + pos += spec->n_rpadding; + } +} + +static char no_grouping[1] = {CHAR_MAX}; + +/* Find the decimal point character(s?), thousands_separator(s?), and + grouping description, either for the current locale if type is + LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or + none if LT_NO_LOCALE. */ +static void +get_locale_info(int type, LocaleInfo *locale_info) +{ + switch (type) { + case LT_CURRENT_LOCALE: { + struct lconv *locale_data = localeconv(); + locale_info->decimal_point = locale_data->decimal_point; + locale_info->thousands_sep = locale_data->thousands_sep; + locale_info->grouping = locale_data->grouping; + break; + } + case LT_DEFAULT_LOCALE: + locale_info->decimal_point = "."; + locale_info->thousands_sep = ","; + locale_info->grouping = "\3"; /* Group every 3 characters. The + (implicit) trailing 0 means repeat + infinitely. */ + break; + case LT_NO_LOCALE: + locale_info->decimal_point = "."; + locale_info->thousands_sep = ""; + locale_info->grouping = no_grouping; + break; + default: + assert(0); + } +} + +/************************************************************************/ +/*********** string formatting ******************************************/ +/************************************************************************/ + +static PyObject * +format_string_internal(PyObject *value, const InternalFormatSpec *format) +{ + Py_ssize_t lpad; + Py_ssize_t rpad; + Py_ssize_t total; + Py_ssize_t pos; + Py_ssize_t len = PyUnicode_GET_SIZE(value); + PyObject *result = NULL; + int maxchar = 127; + + /* sign is not allowed on strings */ + if (format->sign != '\0') { + PyErr_SetString(PyExc_ValueError, + "Sign not allowed in string format specifier"); + goto done; + } + + /* alternate is not allowed on strings */ + if (format->alternate) { + PyErr_SetString(PyExc_ValueError, + "Alternate form (#) not allowed in string format " + "specifier"); + goto done; + } + + /* '=' alignment not allowed on strings */ + if (format->align == '=') { + PyErr_SetString(PyExc_ValueError, + "'=' alignment not allowed " + "in string format specifier"); + goto done; + } + + /* if precision is specified, output no more that format.precision + characters */ + if (format->precision >= 0 && len >= format->precision) { + len = format->precision; + } + + calc_padding(len, format->width, format->align, &lpad, &rpad, &total); + + /* allocate the resulting string */ + result = PyUnicode_New(total, maxchar); + if (result == NULL) + goto done; + + /* Write into that space. First the padding. */ + pos = fill_padding(result, 0, len, + format->fill_char=='\0'?' ':format->fill_char, + lpad, rpad); + + /* Then the source string. */ + PyUnicode_CopyCharacters(result, pos, value, 0, len); + +done: + return result; +} + + +/************************************************************************/ +/*********** long formatting ********************************************/ +/************************************************************************/ + +typedef PyObject* +(*IntOrLongToString)(PyObject *value, int base); + +static PyObject * +format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, + IntOrLongToString tostring) +{ + PyObject *result = NULL; + int maxchar = 127; + PyObject *tmp = NULL; + Py_ssize_t inumeric_chars; + Py_UCS4 sign_char = '\0'; + Py_ssize_t n_digits; /* count of digits need from the computed + string */ + Py_ssize_t n_remainder = 0; /* Used only for 'c' formatting, which + produces non-digits */ + Py_ssize_t n_prefix = 0; /* Count of prefix chars, (e.g., '0x') */ + Py_ssize_t n_total; + Py_ssize_t prefix; + NumberFieldWidths spec; + long x; + + /* Locale settings, either from the actual locale or + from a hard-code pseudo-locale */ + LocaleInfo locale; + + /* no precision allowed on integers */ + if (format->precision != -1) { + PyErr_SetString(PyExc_ValueError, + "Precision not allowed in integer format specifier"); + goto done; + } + + /* special case for character formatting */ + if (format->type == 'c') { + /* error to specify a sign */ + if (format->sign != '\0') { + PyErr_SetString(PyExc_ValueError, + "Sign not allowed with integer" + " format specifier 'c'"); + goto done; + } + + /* taken from unicodeobject.c formatchar() */ + /* Integer input truncated to a character */ +/* XXX: won't work for int */ + x = PyLong_AsLong(value); + if (x == -1 && PyErr_Occurred()) + goto done; + if (x < 0 || x > 0x10ffff) { + PyErr_SetString(PyExc_OverflowError, + "%c arg not in range(0x110000) " + "(wide Python build)"); + goto done; + } + tmp = PyUnicode_FromOrdinal(x); + inumeric_chars = 0; + n_digits = 1; + if (x > maxchar) + maxchar = x; + + /* As a sort-of hack, we tell calc_number_widths that we only + have "remainder" characters. calc_number_widths thinks + these are characters that don't get formatted, only copied + into the output string. We do this for 'c' formatting, + because the characters are likely to be non-digits. */ + n_remainder = 1; + } + else { + int base; + int leading_chars_to_skip = 0; /* Number of characters added by + PyNumber_ToBase that we want to + skip over. */ + + /* Compute the base and how many characters will be added by + PyNumber_ToBase */ + switch (format->type) { + case 'b': + base = 2; + leading_chars_to_skip = 2; /* 0b */ + break; + case 'o': + base = 8; + leading_chars_to_skip = 2; /* 0o */ + break; + case 'x': + case 'X': + base = 16; + leading_chars_to_skip = 2; /* 0x */ + break; + default: /* shouldn't be needed, but stops a compiler warning */ + case 'd': + case 'n': + base = 10; + break; + } + + /* The number of prefix chars is the same as the leading + chars to skip */ + if (format->alternate) + n_prefix = leading_chars_to_skip; + + /* Do the hard part, converting to a string in a given base */ + tmp = tostring(value, base); + if (tmp == NULL || PyUnicode_READY(tmp) == -1) + goto done; + + inumeric_chars = 0; + n_digits = PyUnicode_GET_LENGTH(tmp); + + prefix = inumeric_chars; + + /* Is a sign character present in the output? If so, remember it + and skip it */ + if (PyUnicode_READ_CHAR(tmp, inumeric_chars) == '-') { + sign_char = '-'; + ++prefix; + ++leading_chars_to_skip; + } + + /* Skip over the leading chars (0x, 0b, etc.) */ + n_digits -= leading_chars_to_skip; + inumeric_chars += leading_chars_to_skip; + } + + /* Determine the grouping, separator, and decimal point, if any. */ + get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale); + + /* Calculate how much memory we'll need. */ + n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars, + inumeric_chars + n_digits, n_remainder, 0, &locale, format); + + /* Allocate the memory. */ + result = PyUnicode_New(n_total, maxchar); + if (!result) + goto done; + + /* Populate the memory. */ + fill_number(result, 0, &spec, tmp, inumeric_chars, inumeric_chars + n_digits, + tmp, prefix, + format->fill_char == '\0' ? ' ' : format->fill_char, + &locale, format->type == 'X'); + +done: + Py_XDECREF(tmp); + return result; +} + +/************************************************************************/ +/*********** float formatting *******************************************/ +/************************************************************************/ + +static PyObject* +strtounicode(char *charbuffer, Py_ssize_t len) +{ + return PyUnicode_FromKindAndData(PyUnicode_1BYTE_KIND, charbuffer, len); +} + +/* much of this is taken from unicodeobject.c */ +static PyObject * +format_float_internal(PyObject *value, + const InternalFormatSpec *format) +{ + char *buf = NULL; /* buffer returned from PyOS_double_to_string */ + Py_ssize_t n_digits; + Py_ssize_t n_remainder; + Py_ssize_t n_total; + int has_decimal; + double val; + Py_ssize_t precision = format->precision; + Py_ssize_t default_precision = 6; + Py_UCS4 type = format->type; + int add_pct = 0; + Py_ssize_t index; + NumberFieldWidths spec; + int flags = 0; + PyObject *result = NULL; + int maxchar = 127; + Py_UCS4 sign_char = '\0'; + int float_type; /* Used to see if we have a nan, inf, or regular float. */ + PyObject *unicode_tmp = NULL; + + /* Locale settings, either from the actual locale or + from a hard-code pseudo-locale */ + LocaleInfo locale; + + if (format->alternate) + flags |= Py_DTSF_ALT; + + if (type == '\0') { + /* Omitted type specifier. Behaves in the same way as repr(x) + and str(x) if no precision is given, else like 'g', but with + at least one digit after the decimal point. */ + flags |= Py_DTSF_ADD_DOT_0; + type = 'r'; + default_precision = 0; + } + + if (type == 'n') + /* 'n' is the same as 'g', except for the locale used to + format the result. We take care of that later. */ + type = 'g'; + + val = PyFloat_AsDouble(value); + if (val == -1.0 && PyErr_Occurred()) + goto done; + + if (type == '%') { + type = 'f'; + val *= 100; + add_pct = 1; + } + + if (precision < 0) + precision = default_precision; + else if (type == 'r') + type = 'g'; + + /* Cast "type", because if we're in unicode we need to pass a + 8-bit char. This is safe, because we've restricted what "type" + can be. */ + buf = PyOS_double_to_string(val, (char)type, precision, flags, + &float_type); + if (buf == NULL) + goto done; + n_digits = strlen(buf); + + if (add_pct) { + /* We know that buf has a trailing zero (since we just called + strlen() on it), and we don't use that fact any more. So we + can just write over the trailing zero. */ + buf[n_digits] = '%'; + n_digits += 1; + } + + /* Since there is no unicode version of PyOS_double_to_string, + just use the 8 bit version and then convert to unicode. */ + unicode_tmp = strtounicode(buf, n_digits); + if (unicode_tmp == NULL) + goto done; + index = 0; + + /* Is a sign character present in the output? If so, remember it + and skip it */ + if (PyUnicode_READ_CHAR(unicode_tmp, index) == '-') { + sign_char = '-'; + ++index; + --n_digits; + } + + /* Determine if we have any "remainder" (after the digits, might include + decimal or exponent or both (or neither)) */ + parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal); + + /* Determine the grouping, separator, and decimal point, if any. */ + get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale); + + /* Calculate how much memory we'll need. */ + n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, + index + n_digits, n_remainder, has_decimal, + &locale, format); + + /* Allocate the memory. */ + result = PyUnicode_New(n_total, maxchar); + if (result == NULL) + goto done; + + /* Populate the memory. */ + fill_number(result, 0, &spec, unicode_tmp, index, index + n_digits, + NULL, 0, + format->fill_char == '\0' ? ' ' : format->fill_char, &locale, + 0); + +done: + PyMem_Free(buf); + Py_DECREF(unicode_tmp); + return result; +} + +/************************************************************************/ +/*********** complex formatting *****************************************/ +/************************************************************************/ + +static PyObject * +format_complex_internal(PyObject *value, + const InternalFormatSpec *format) +{ + double re; + double im; + char *re_buf = NULL; /* buffer returned from PyOS_double_to_string */ + char *im_buf = NULL; /* buffer returned from PyOS_double_to_string */ + + InternalFormatSpec tmp_format = *format; + Py_ssize_t n_re_digits; + Py_ssize_t n_im_digits; + Py_ssize_t n_re_remainder; + Py_ssize_t n_im_remainder; + Py_ssize_t n_re_total; + Py_ssize_t n_im_total; + int re_has_decimal; + int im_has_decimal; + Py_ssize_t precision = format->precision; + Py_ssize_t default_precision = 6; + Py_UCS4 type = format->type; + Py_ssize_t i_re; + Py_ssize_t i_im; + NumberFieldWidths re_spec; + NumberFieldWidths im_spec; + int flags = 0; + PyObject *result = NULL; + int maxchar = 127; + int rkind; + void *rdata; + Py_ssize_t index; + Py_UCS4 re_sign_char = '\0'; + Py_UCS4 im_sign_char = '\0'; + int re_float_type; /* Used to see if we have a nan, inf, or regular float. */ + int im_float_type; + int add_parens = 0; + int skip_re = 0; + Py_ssize_t lpad; + Py_ssize_t rpad; + Py_ssize_t total; + PyObject *re_unicode_tmp = NULL; + PyObject *im_unicode_tmp = NULL; + + /* Locale settings, either from the actual locale or + from a hard-code pseudo-locale */ + LocaleInfo locale; + + /* Zero padding is not allowed. */ + if (format->fill_char == '0') { + PyErr_SetString(PyExc_ValueError, + "Zero padding is not allowed in complex format " + "specifier"); + goto done; + } + + /* Neither is '=' alignment . */ + if (format->align == '=') { + PyErr_SetString(PyExc_ValueError, + "'=' alignment flag is not allowed in complex format " + "specifier"); + goto done; + } + + re = PyComplex_RealAsDouble(value); + if (re == -1.0 && PyErr_Occurred()) + goto done; + im = PyComplex_ImagAsDouble(value); + if (im == -1.0 && PyErr_Occurred()) + goto done; + + if (format->alternate) + flags |= Py_DTSF_ALT; + + if (type == '\0') { + /* Omitted type specifier. Should be like str(self). */ + type = 'r'; + default_precision = 0; + if (re == 0.0 && copysign(1.0, re) == 1.0) + skip_re = 1; + else + add_parens = 1; + } + + if (type == 'n') + /* 'n' is the same as 'g', except for the locale used to + format the result. We take care of that later. */ + type = 'g'; + + if (precision < 0) + precision = default_precision; + else if (type == 'r') + type = 'g'; + + /* Cast "type", because if we're in unicode we need to pass a + 8-bit char. This is safe, because we've restricted what "type" + can be. */ + re_buf = PyOS_double_to_string(re, (char)type, precision, flags, + &re_float_type); + if (re_buf == NULL) + goto done; + im_buf = PyOS_double_to_string(im, (char)type, precision, flags, + &im_float_type); + if (im_buf == NULL) + goto done; + + n_re_digits = strlen(re_buf); + n_im_digits = strlen(im_buf); + + /* Since there is no unicode version of PyOS_double_to_string, + just use the 8 bit version and then convert to unicode. */ + re_unicode_tmp = strtounicode(re_buf, n_re_digits); + if (re_unicode_tmp == NULL) + goto done; + i_re = 0; + + im_unicode_tmp = strtounicode(im_buf, n_im_digits); + if (im_unicode_tmp == NULL) + goto done; + i_im = 0; + + /* Is a sign character present in the output? If so, remember it + and skip it */ + if (PyUnicode_READ_CHAR(re_unicode_tmp, i_re) == '-') { + re_sign_char = '-'; + ++i_re; + --n_re_digits; + } + if (PyUnicode_READ_CHAR(im_unicode_tmp, i_im) == '-') { + im_sign_char = '-'; + ++i_im; + --n_im_digits; + } + + /* Determine if we have any "remainder" (after the digits, might include + decimal or exponent or both (or neither)) */ + parse_number(re_unicode_tmp, i_re, i_re + n_re_digits, + &n_re_remainder, &re_has_decimal); + parse_number(im_unicode_tmp, i_im, i_im + n_im_digits, + &n_im_remainder, &im_has_decimal); + + /* Determine the grouping, separator, and decimal point, if any. */ + get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale); + + /* Turn off any padding. We'll do it later after we've composed + the numbers without padding. */ + tmp_format.fill_char = '\0'; + tmp_format.align = '<'; + tmp_format.width = -1; + + /* Calculate how much memory we'll need. */ + n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, re_unicode_tmp, + i_re, i_re + n_re_digits, n_re_remainder, + re_has_decimal, &locale, &tmp_format); + + /* Same formatting, but always include a sign, unless the real part is + * going to be omitted, in which case we use whatever sign convention was + * requested by the original format. */ + if (!skip_re) + tmp_format.sign = '+'; + n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, im_unicode_tmp, + i_im, i_im + n_im_digits, n_im_remainder, + im_has_decimal, &locale, &tmp_format); + + if (skip_re) + n_re_total = 0; + + /* Add 1 for the 'j', and optionally 2 for parens. */ + calc_padding(n_re_total + n_im_total + 1 + add_parens * 2, + format->width, format->align, &lpad, &rpad, &total); + + result = PyUnicode_New(total, maxchar); + if (result == NULL) + goto done; + rkind = PyUnicode_KIND(result); + rdata = PyUnicode_DATA(result); + + /* Populate the memory. First, the padding. */ + index = fill_padding(result, 0, + n_re_total + n_im_total + 1 + add_parens * 2, + format->fill_char=='\0' ? ' ' : format->fill_char, + lpad, rpad); + + if (add_parens) + PyUnicode_WRITE(rkind, rdata, index++, '('); + + if (!skip_re) { + fill_number(result, index, &re_spec, re_unicode_tmp, + i_re, i_re + n_re_digits, NULL, 0, 0, &locale, 0); + index += n_re_total; + } + fill_number(result, index, &im_spec, im_unicode_tmp, + i_im, i_im + n_im_digits, NULL, 0, 0, &locale, 0); + index += n_im_total; + PyUnicode_WRITE(rkind, rdata, index++, 'j'); + + if (add_parens) + PyUnicode_WRITE(rkind, rdata, index++, ')'); + +done: + PyMem_Free(re_buf); + PyMem_Free(im_buf); + Py_XDECREF(re_unicode_tmp); + Py_XDECREF(im_unicode_tmp); + return result; +} + +/************************************************************************/ +/*********** built in formatters ****************************************/ +/************************************************************************/ +PyObject * +_PyUnicode_FormatAdvanced(PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, Py_ssize_t end) +{ + InternalFormatSpec format; + PyObject *result = NULL; + + /* check for the special case of zero length format spec, make + it equivalent to str(obj) */ + if (start == end) { + result = PyObject_Str(obj); + goto done; + } + + /* parse the format_spec */ + if (!parse_internal_render_format_spec(format_spec, start, end, + &format, 's', '<')) + goto done; + + /* type conversion? */ + switch (format.type) { + case 's': + /* no type conversion needed, already a string. do the formatting */ + result = format_string_internal(obj, &format); + break; + default: + /* unknown */ + unknown_presentation_type(format.type, obj->ob_type->tp_name); + goto done; + } + +done: + return result; +} + +static PyObject* +format_int_or_long(PyObject* obj, PyObject* format_spec, + Py_ssize_t start, Py_ssize_t end, + IntOrLongToString tostring) +{ + PyObject *result = NULL; + PyObject *tmp = NULL; + InternalFormatSpec format; + + /* check for the special case of zero length format spec, make + it equivalent to str(obj) */ + if (start == end) { + result = PyObject_Str(obj); + goto done; + } + + /* parse the format_spec */ + if (!parse_internal_render_format_spec(format_spec, start, end, + &format, 'd', '>')) + goto done; + + /* type conversion? */ + switch (format.type) { + case 'b': + case 'c': + case 'd': + case 'o': + case 'x': + case 'X': + case 'n': + /* no type conversion needed, already an int (or long). do + the formatting */ + result = format_int_or_long_internal(obj, &format, tostring); + break; + + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case '%': + /* convert to float */ + tmp = PyNumber_Float(obj); + if (tmp == NULL) + goto done; + result = format_float_internal(tmp, &format); + break; + + default: + /* unknown */ + unknown_presentation_type(format.type, obj->ob_type->tp_name); + goto done; + } + +done: + Py_XDECREF(tmp); + return result; +} + +/* Need to define long_format as a function that will convert a long + to a string. In 3.0, _PyLong_Format has the correct signature. */ +#define long_format _PyLong_Format + +PyObject * +_PyLong_FormatAdvanced(PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, Py_ssize_t end) +{ + return format_int_or_long(obj, format_spec, start, end, + long_format); +} + +PyObject * +_PyFloat_FormatAdvanced(PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, Py_ssize_t end) +{ + PyObject *result = NULL; + InternalFormatSpec format; + + /* check for the special case of zero length format spec, make + it equivalent to str(obj) */ + if (start == end) { + result = PyObject_Str(obj); + goto done; + } + + /* parse the format_spec */ + if (!parse_internal_render_format_spec(format_spec, start, end, + &format, '\0', '>')) + goto done; + + /* type conversion? */ + switch (format.type) { + case '\0': /* No format code: like 'g', but with at least one decimal. */ + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'n': + case '%': + /* no conversion, already a float. do the formatting */ + result = format_float_internal(obj, &format); + break; + + default: + /* unknown */ + unknown_presentation_type(format.type, obj->ob_type->tp_name); + goto done; + } + +done: + return result; +} + +PyObject * +_PyComplex_FormatAdvanced(PyObject *obj, + PyObject *format_spec, + Py_ssize_t start, Py_ssize_t end) +{ + PyObject *result = NULL; + InternalFormatSpec format; + + /* check for the special case of zero length format spec, make + it equivalent to str(obj) */ + if (start == end) { + result = PyObject_Str(obj); + goto done; + } + + /* parse the format_spec */ + if (!parse_internal_render_format_spec(format_spec, start, end, + &format, '\0', '>')) + goto done; + + /* type conversion? */ + switch (format.type) { + case '\0': /* No format code: like 'g', but with at least one decimal. */ + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'n': + /* no conversion, already a complex. do the formatting */ + result = format_complex_internal(obj, &format); + break; + + default: + /* unknown */ + unknown_presentation_type(format.type, obj->ob_type->tp_name); + goto done; + } + +done: + return result; +} diff --git a/Python/getargs.c b/Python/getargs.c index c3da368604..0e7d9c4350 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -546,9 +546,6 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -#define UNICODE_DEFAULT_ENCODING(arg) \ - _PyUnicode_AsDefaultEncodedString(arg) - /* Format an error message generated by convertsimple(). */ static char * @@ -611,7 +608,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, const char *format = *p_format; char c = *format++; - PyObject *uarg; + char *sarg; switch (c) { @@ -838,8 +835,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'C': {/* unicode char */ int *p = va_arg(*p_va, int *); if (PyUnicode_Check(arg) && - PyUnicode_GET_SIZE(arg) == 1) - *p = PyUnicode_AS_UNICODE(arg)[0]; + PyUnicode_GET_LENGTH(arg) == 1) { + int kind = PyUnicode_KIND(arg); + void *data = PyUnicode_DATA(arg); + *p = PyUnicode_READ(kind, data, 0); + } else return converterr("a unicode character", arg, msgbuf, bufsize); break; @@ -889,13 +889,12 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (c == 'z' && arg == Py_None) PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) + Py_ssize_t len; + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, - PyBytes_AS_STRING(uarg), PyBytes_GET_SIZE(uarg), - 1, 0); + PyBuffer_FillInfo(p, arg, sarg, len, 1, 0); } else { /* any buffer-like object */ char *buf; @@ -918,12 +917,13 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) + Py_ssize_t len; + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); - STORE_SIZE(PyBytes_GET_SIZE(uarg)); + *p = sarg; + STORE_SIZE(len); } else { /* any buffer-like object */ /* XXX Really? */ @@ -937,22 +937,22 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } else { /* "s" or "z" */ char **p = va_arg(*p_va, char **); - uarg = NULL; + Py_ssize_t len; + sarg = NULL; if (c == 'z' && arg == Py_None) *p = NULL; else if (PyUnicode_Check(arg)) { - uarg = UNICODE_DEFAULT_ENCODING(arg); - if (uarg == NULL) + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); - *p = PyBytes_AS_STRING(uarg); + *p = sarg; } else return converterr(c == 'z' ? "str or None" : "str", arg, msgbuf, bufsize); - if (*p != NULL && uarg != NULL && - (Py_ssize_t) strlen(*p) != PyBytes_GET_SIZE(uarg)) + if (*p != NULL && sarg != NULL && (Py_ssize_t) strlen(*p) != len) return converterr( c == 'z' ? "str without null bytes or None" : "str without null bytes", @@ -976,6 +976,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); + if (*p == NULL) + RETURN_ERR_OCCURRED; STORE_SIZE(PyUnicode_GET_SIZE(arg)); } else @@ -987,6 +989,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *p = NULL; else if (PyUnicode_Check(arg)) { *p = PyUnicode_AS_UNICODE(arg); + if (*p == NULL) + RETURN_ERR_OCCURRED; if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) return converterr( "str without null character or None", diff --git a/Python/import.c b/Python/import.c index 24df985d46..4afdb7058c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -118,12 +118,12 @@ typedef unsigned short mode_t; #define MAGIC (3190 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" -static const Py_UNICODE CACHEDIR_UNICODE[] = { +static const Py_UCS4 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; -static const Py_UNICODE PYC_TAG_UNICODE[] = { +static const Py_UCS4 PYC_TAG_UNICODE[] = { 'c', 'p', 'y', 't', 'h', 'o', 'n', '-', PY_MAJOR_VERSION + 48, PY_MINOR_VERSION + 48, '\0'}; #undef QUOTE #undef STRIFY @@ -762,7 +762,7 @@ remove_module(PyObject *name) static PyObject * get_sourcefile(PyObject *filename); static PyObject *make_source_pathname(PyObject *pathname); -static PyObject* make_compiled_pathname(Py_UNICODE *pathname, int debug); +static PyObject* make_compiled_pathname(PyObject *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 @@ -886,10 +886,10 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, /* Like strrchr(string, '/') but searches for the rightmost of either SEP or ALTSEP, if the latter is defined. */ -static Py_UNICODE* -rightmost_sep(Py_UNICODE *s) +static Py_UCS4* +rightmost_sep(Py_UCS4 *s) { - Py_UNICODE *found, c; + Py_UCS4 *found, c; for (found = NULL; (c = *s); s++) { if (c == SEP #ifdef ALTSEP @@ -912,15 +912,21 @@ rightmost_sep(Py_UNICODE *s) foo.py -> __pycache__/foo..pyc */ static PyObject* -make_compiled_pathname(Py_UNICODE *pathname, int debug) +make_compiled_pathname(PyObject *pathstr, int debug) { - Py_UNICODE buf[MAXPATHLEN]; + Py_UCS4 *pathname; + Py_UCS4 buf[MAXPATHLEN]; size_t buflen = (size_t)MAXPATHLEN; - size_t len = Py_UNICODE_strlen(pathname); + size_t len; size_t i, save; - Py_UNICODE *pos; + Py_UCS4 *pos; int sep = SEP; + pathname = PyUnicode_AsUCS4Copy(pathstr); + if (!pathname) + return NULL; + len = Py_UCS4_strlen(pathname); + /* Sanity check that the buffer has roughly enough space to hold what will eventually be the full path to the compiled file. The 5 extra bytes include the slash afer __pycache__, the two extra dots, the @@ -930,8 +936,10 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) sanity check before writing the extension to ensure we do not overflow the buffer. */ - if (len + Py_UNICODE_strlen(CACHEDIR_UNICODE) + Py_UNICODE_strlen(PYC_TAG_UNICODE) + 5 > buflen) + if (len + Py_UCS4_strlen(CACHEDIR_UNICODE) + Py_UCS4_strlen(PYC_TAG_UNICODE) + 5 > buflen) { + PyMem_Free(pathname); return NULL; + } /* Find the last path separator and copy everything from the start of the source string up to and including the separator. @@ -943,24 +951,28 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) else { sep = *pos; i = pos - pathname + 1; - Py_UNICODE_strncpy(buf, pathname, i); + Py_UCS4_strncpy(buf, pathname, i); } save = i; buf[i++] = '\0'; /* Add __pycache__/ */ - Py_UNICODE_strcat(buf, CACHEDIR_UNICODE); - i += Py_UNICODE_strlen(CACHEDIR_UNICODE) - 1; + Py_UCS4_strcat(buf, CACHEDIR_UNICODE); + i += Py_UCS4_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. */ - Py_UNICODE_strcat(buf, pathname + save); - pos = Py_UNICODE_strrchr(buf + i, '.'); + Py_UCS4_strcat(buf, pathname + save); + pos = Py_UCS4_strrchr(buf + i, '.'); if (pos != NULL) *++pos = '\0'; - Py_UNICODE_strcat(buf, PYC_TAG_UNICODE); + + /* pathname is not used from here on. */ + PyMem_Free(pathname); + + Py_UCS4_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,7 +1022,7 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) #if 0 printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); #endif - len = Py_UNICODE_strlen(buf); + len = Py_UCS4_strlen(buf); if (len + 5 > buflen) return NULL; buf[len] = '.'; len++; @@ -1018,7 +1030,7 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) buf[len] = 'y'; len++; buf[len] = debug ? 'c' : 'o'; len++; assert(len <= buflen); - return PyUnicode_FromUnicode(buf, len); + return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, len); } @@ -1033,14 +1045,16 @@ make_compiled_pathname(Py_UNICODE *pathname, int debug) static PyObject* make_source_pathname(PyObject *pathobj) { - Py_UNICODE buf[MAXPATHLEN]; - Py_UNICODE *pathname; - Py_UNICODE *left, *right, *dot0, *dot1, sep; + Py_UCS4 buf[MAXPATHLEN]; + Py_UCS4 *pathname; + Py_UCS4 *left, *right, *dot0, *dot1, sep; size_t i, j; - if (PyUnicode_GET_SIZE(pathobj) > MAXPATHLEN) + if (PyUnicode_GET_LENGTH(pathobj) > MAXPATHLEN) + return NULL; + pathname = PyUnicode_AsUCS4Copy(pathobj); + if (!pathname) 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 @@ -1057,31 +1071,35 @@ make_source_pathname(PyObject *pathobj) left = pathname; else left++; - if (right-left != Py_UNICODE_strlen(CACHEDIR_UNICODE) || - Py_UNICODE_strncmp(left, CACHEDIR_UNICODE, right-left) != 0) - return NULL; + if (right-left != Py_UCS4_strlen(CACHEDIR_UNICODE) || + Py_UCS4_strncmp(left, CACHEDIR_UNICODE, right-left) != 0) + goto error; /* Now verify that the path component to the right of the last slash has two dots in it. */ - if ((dot0 = Py_UNICODE_strchr(right + 1, '.')) == NULL) - return NULL; - if ((dot1 = Py_UNICODE_strchr(dot0 + 1, '.')) == NULL) - return NULL; + if ((dot0 = Py_UCS4_strchr(right + 1, '.')) == NULL) + goto error; + if ((dot1 = Py_UCS4_strchr(dot0 + 1, '.')) == NULL) + goto error; /* Too many dots? */ - if (Py_UNICODE_strchr(dot1 + 1, '.') != NULL) - return NULL; + if (Py_UCS4_strchr(dot1 + 1, '.') != NULL) + goto error; /* This is a PEP 3147 path. Start by copying everything from the start of pathname up to and including the leftmost slash. Then copy the file's basename, removing the magic tag and adding a .py suffix. */ - Py_UNICODE_strncpy(buf, pathname, (i=left-pathname)); - Py_UNICODE_strncpy(buf+i, right+1, (j=dot0-right)); + Py_UCS4_strncpy(buf, pathname, (i=left-pathname)); + Py_UCS4_strncpy(buf+i, right+1, (j=dot0-right)); buf[i+j] = 'p'; buf[i+j+1] = 'y'; - return PyUnicode_FromUnicode(buf, i+j+2); + PyMem_Free(pathname); + return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, i+j+2); + error: + PyMem_Free(pathname); + return NULL; } /* Given a pathname for a Python source file, its time of last @@ -1250,6 +1268,7 @@ static void write_compiled_module(PyCodeObject *co, PyObject *cpathname, struct stat *srcstat) { + Py_UCS4 *cpathname_ucs4; FILE *fp; time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ @@ -1267,18 +1286,23 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, PyObject *cpathbytes; #endif PyObject *dirname; - Py_UNICODE *dirsep; + Py_UCS4 *dirsep; int res, ok; /* Ensure that the __pycache__ directory exists. */ - dirsep = rightmost_sep(PyUnicode_AS_UNICODE(cpathname)); + cpathname_ucs4 = PyUnicode_AsUCS4Copy(cpathname); + if (!cpathname_ucs4) + return; + dirsep = rightmost_sep(cpathname_ucs4); if (dirsep == NULL) { if (Py_VerboseFlag) PySys_FormatStderr("# no %s path found %R\n", CACHEDIR, cpathname); return; } - dirname = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(cpathname), - dirsep - PyUnicode_AS_UNICODE(cpathname)); + dirname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + cpathname_ucs4, + dirsep - cpathname_ucs4); + PyMem_Free(cpathname_ucs4); if (dirname == NULL) { PyErr_Clear(); return; @@ -1461,9 +1485,7 @@ load_source_module(PyObject *name, PyObject *pathname, FILE *fp) goto error; } #endif - cpathname = make_compiled_pathname( - PyUnicode_AS_UNICODE(pathname), - !Py_OptimizeFlag); + cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag); if (cpathname != NULL) fpc = check_compiled_module(pathname, st.st_mtime, cpathname); @@ -1512,16 +1534,18 @@ static PyObject * get_sourcefile(PyObject *filename) { Py_ssize_t len; - Py_UNICODE *fileuni; + Py_UCS4 *fileuni; PyObject *py; struct stat statbuf; - len = PyUnicode_GET_SIZE(filename); + len = PyUnicode_GET_LENGTH(filename); if (len == 0) Py_RETURN_NONE; /* don't match *.pyc or *.pyo? */ - fileuni = PyUnicode_AS_UNICODE(filename); + fileuni = PyUnicode_AsUCS4Copy(filename); + if (!fileuni) + return NULL; if (len < 5 || fileuni[len-4] != '.' || (fileuni[len-3] != 'p' && fileuni[len-3] != 'P') @@ -1535,7 +1559,7 @@ get_sourcefile(PyObject *filename) py = make_source_pathname(filename); if (py == NULL) { PyErr_Clear(); - py = PyUnicode_FromUnicode(fileuni, len - 1); + py = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, fileuni, len - 1); } if (py == NULL) goto error; @@ -1548,6 +1572,7 @@ get_sourcefile(PyObject *filename) error: PyErr_Clear(); unchanged: + PyMem_Free(fileuni); Py_INCREF(filename); return filename; } @@ -1739,8 +1764,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, PyObject *path_hooks, PyObject *path_importer_cache, PyObject **p_path, PyObject **p_loader, struct filedescr **p_fd) { - Py_UNICODE buf[MAXPATHLEN+1]; - Py_ssize_t buflen = MAXPATHLEN+1; + Py_UCS4 buf[MAXPATHLEN+1]; PyObject *path_unicode, *filename; Py_ssize_t len; struct stat statbuf; @@ -1759,15 +1783,15 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, else return 0; - len = PyUnicode_GET_SIZE(path_unicode); - if (len + 2 + PyUnicode_GET_SIZE(name) + MAXSUFFIXSIZE >= buflen) { + len = PyUnicode_GET_LENGTH(path_unicode); + if (!PyUnicode_AsUCS4(path_unicode, buf, PY_ARRAY_LENGTH(buf), 1)) { Py_DECREF(path_unicode); - return 0; /* Too long */ + PyErr_Clear(); + return 0; } - Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(path_unicode)); Py_DECREF(path_unicode); - if (Py_UNICODE_strlen(buf) != len) + if (Py_UCS4_strlen(buf) != len) return 0; /* path contains '\0' */ /* sys.path_hooks import hook */ @@ -1804,10 +1828,14 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, #endif ) buf[len++] = SEP; - Py_UNICODE_strcpy(buf+len, PyUnicode_AS_UNICODE(name)); - len += PyUnicode_GET_SIZE(name); + if (!PyUnicode_AsUCS4(name, buf+len, PY_ARRAY_LENGTH(buf)-len, 1)) { + PyErr_Clear(); + return 0; + } + len += PyUnicode_GET_LENGTH(name); - filename = PyUnicode_FromUnicode(buf, len); + filename = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + buf, len); if (filename == NULL) return -1; @@ -1989,6 +2017,12 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, if (p_loader != NULL) *p_loader = NULL; + if (PyUnicode_GET_LENGTH(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; @@ -2704,7 +2738,7 @@ static PyObject *get_parent(PyObject *globals, int level); static PyObject *load_next(PyObject *mod, PyObject *altmod, PyObject *inputname, PyObject **p_outputname, - Py_UNICODE *buf, Py_ssize_t *p_buflen, + Py_UCS4 *buf, Py_ssize_t *p_buflen, Py_ssize_t bufsize); static int mark_miss(PyObject *name); static int ensure_fromlist(PyObject *mod, PyObject *fromlist, @@ -2718,37 +2752,47 @@ static PyObject * import_module_level(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { - Py_UNICODE buf[MAXPATHLEN+1]; + Py_UCS4 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; + Py_ssize_t sep, altsep; - nameunicode = PyUnicode_AS_UNICODE(name); + if (PyUnicode_READY(name)) + return NULL; - if (Py_UNICODE_strchr(nameunicode, SEP) != NULL + sep = PyUnicode_FindChar(name, SEP, 0, PyUnicode_GET_LENGTH(name), 1); + if (sep == -2) + return NULL; #ifdef ALTSEP - || Py_UNICODE_strchr(nameunicode, ALTSEP) != NULL + altsep = PyUnicode_FindChar(name, ALTSEP, 0, PyUnicode_GET_LENGTH(name), 1); + if (altsep == -2) + return NULL; +#else + altsep = -1; #endif - ) { + if (sep != -1 || altsep != -1) + { PyErr_SetString(PyExc_ImportError, "Import by filename is not supported."); return NULL; } parent = get_parent(globals, &parent_name, level); - if (parent == NULL) + if (parent == NULL) { return NULL; + } - buflen = PyUnicode_GET_SIZE(parent_name); - if (buflen+1 > bufsize) { + if (PyUnicode_READY(parent_name)) + return NULL; + buflen = PyUnicode_GET_LENGTH(parent_name); + if (!PyUnicode_AsUCS4(parent_name, buf, PY_ARRAY_LENGTH(buf), 1)) { 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, @@ -2799,7 +2843,8 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, Py_DECREF(head); - ensure_name = PyUnicode_FromUnicode(buf, Py_UNICODE_strlen(buf)); + ensure_name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + buf, Py_UCS4_strlen(buf)); if (ensure_name == NULL) { Py_DECREF(tail); return NULL; @@ -2859,8 +2904,6 @@ PyImport_ImportModuleLevel(const char *name, PyObject *globals, PyObject *locals static PyObject * 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; @@ -2897,7 +2940,7 @@ get_parent(PyObject *globals, PyObject **p_name, int level) "__package__ set to non-string"); return NULL; } - if (PyUnicode_GET_SIZE(pkgname) == 0) { + if (PyUnicode_GET_LENGTH(pkgname) == 0) { if (level > 0) { PyErr_SetString(PyExc_ValueError, "Attempted relative import in non-package"); @@ -2905,12 +2948,8 @@ get_parent(PyObject *globals, PyObject **p_name, int level) } goto return_none; } - if (PyUnicode_GET_SIZE(pkgname)+1 > bufsize) { - PyErr_SetString(PyExc_ValueError, - "Package name too long"); - return NULL; - } - Py_UNICODE_strcpy(name, PyUnicode_AS_UNICODE(pkgname)); + Py_INCREF(pkgname); + nameobj = pkgname; } else { /* __package__ not set, so figure it out and set it */ modname = PyDict_GetItem(globals, namestr); @@ -2922,74 +2961,71 @@ get_parent(PyObject *globals, PyObject **p_name, int level) /* __path__ is set, so modname is already the package name */ int error; - if (PyUnicode_GET_SIZE(modname)+1 > bufsize) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - Py_UNICODE_strcpy(name, PyUnicode_AS_UNICODE(modname)); error = PyDict_SetItem(globals, pkgstr, modname); if (error) { PyErr_SetString(PyExc_ValueError, "Could not set __package__"); return NULL; } + Py_INCREF(modname); + nameobj = modname; } else { /* Normal module, so work out the package name if any */ - 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, - "Attempted relative import in non-package"); + len = PyUnicode_FindChar(modname, '.', + 0, PyUnicode_GET_LENGTH(modname), -1); + if (len == -2) return NULL; - } - if (lastdot == NULL) { - error = PyDict_SetItem(globals, pkgstr, Py_None); - if (error) { + if (len < 0) { + if (level > 0) { + PyErr_SetString(PyExc_ValueError, + "Attempted relative import in non-package"); + return NULL; + } + if (PyDict_SetItem(globals, pkgstr, Py_None)) { PyErr_SetString(PyExc_ValueError, "Could not set __package__"); return NULL; } goto return_none; } - len = lastdot - start; - if (len+1 > bufsize) { + pkgname = PyUnicode_Substring(modname, 0, len); + if (pkgname == NULL) + return NULL; + if (PyDict_SetItem(globals, pkgstr, pkgname)) { + Py_DECREF(pkgname); PyErr_SetString(PyExc_ValueError, - "Module name too long"); + "Could not set __package__"); return NULL; } - Py_UNICODE_strncpy(name, start, len); - name[len] = '\0'; - pkgname = PyUnicode_FromUnicode(name, len); - if (pkgname == NULL) { + nameobj = pkgname; + } + } + if (level > 1) { + Py_ssize_t dot, end = PyUnicode_GET_LENGTH(nameobj); + PyObject *newname; + while (--level > 0) { + dot = PyUnicode_FindChar(nameobj, '.', 0, end, -1); + if (dot == -2) { + Py_DECREF(nameobj); return NULL; } - error = PyDict_SetItem(globals, pkgstr, pkgname); - Py_DECREF(pkgname); - if (error) { + if (dot < 0) { + Py_DECREF(nameobj); PyErr_SetString(PyExc_ValueError, - "Could not set __package__"); + "Attempted relative import beyond " + "toplevel package"); return NULL; } + end = dot; } - } - while (--level > 0) { - Py_UNICODE *dot = Py_UNICODE_strrchr(name, '.'); - if (dot == NULL) { - PyErr_SetString(PyExc_ValueError, - "Attempted relative import beyond " - "toplevel package"); + newname = PyUnicode_Substring(nameobj, 0, end); + Py_DECREF(nameobj); + if (newname == NULL) return NULL; - } - *dot = '\0'; + nameobj = newname; } - nameobj = PyUnicode_FromUnicode(name, Py_UNICODE_strlen(name)); - if (nameobj == NULL) - return NULL; - modules = PyImport_GetModuleDict(); parent = PyDict_GetItem(modules, nameobj); if (parent == NULL) { @@ -3021,7 +3057,7 @@ get_parent(PyObject *globals, PyObject **p_name, int level) If this is violated... Who cares? */ return_none: - nameobj = PyUnicode_FromUnicode(NULL, 0); + nameobj = PyUnicode_New(0, 0); if (nameobj == NULL) return NULL; *p_name = nameobj; @@ -3032,28 +3068,28 @@ return_none: static PyObject * load_next(PyObject *mod, PyObject *altmod, PyObject *inputname, PyObject **p_outputname, - Py_UNICODE *buf, Py_ssize_t *p_buflen, Py_ssize_t bufsize) + Py_UCS4 *buf, Py_ssize_t *p_buflen, Py_ssize_t bufsize) { - const Py_UNICODE *dot; + Py_UCS4 *dot; Py_ssize_t len; - Py_UNICODE *p; + Py_UCS4 *p; PyObject *fullname, *name, *result, *mark_name; - const Py_UNICODE *nameuni; + const Py_UCS4 *nameuni; *p_outputname = NULL; - if (PyUnicode_GET_SIZE(inputname) == 0) { + if (PyUnicode_GET_LENGTH(inputname) == 0) { /* completely empty module name should only happen in 'from . import' (or '__import__("")')*/ Py_INCREF(mod); return mod; } - nameuni = PyUnicode_AS_UNICODE(inputname); + nameuni = PyUnicode_AsUCS4Copy(inputname); if (nameuni == NULL) return NULL; - dot = Py_UNICODE_strchr(nameuni, '.'); + dot = Py_UCS4_strchr(nameuni, '.'); if (dot != NULL) { len = dot - nameuni; if (len == 0) { @@ -3063,7 +3099,7 @@ load_next(PyObject *mod, PyObject *altmod, } } else - len = PyUnicode_GET_SIZE(inputname); + len = PyUnicode_GET_LENGTH(inputname); if (*p_buflen+len+1 >= bufsize) { PyErr_SetString(PyExc_ValueError, @@ -3076,14 +3112,16 @@ load_next(PyObject *mod, PyObject *altmod, *p++ = '.'; *p_buflen += 1; } - Py_UNICODE_strncpy(p, nameuni, len); + Py_UCS4_strncpy(p, nameuni, len); p[len] = '\0'; *p_buflen += len; - fullname = PyUnicode_FromUnicode(buf, *p_buflen); + fullname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + buf, *p_buflen); if (fullname == NULL) return NULL; - name = PyUnicode_FromUnicode(p, len); + name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + p, len); if (name == NULL) { Py_DECREF(fullname); return NULL; @@ -3096,7 +3134,8 @@ load_next(PyObject *mod, PyObject *altmod, result = import_submodule(altmod, name, name); Py_DECREF(name); if (result != NULL && result != Py_None) { - mark_name = PyUnicode_FromUnicode(buf, *p_buflen); + mark_name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + buf, *p_buflen); if (mark_name == NULL) { Py_DECREF(result); return NULL; @@ -3107,7 +3146,7 @@ load_next(PyObject *mod, PyObject *altmod, return NULL; } Py_DECREF(mark_name); - Py_UNICODE_strncpy(buf, nameuni, len); + Py_UCS4_strncpy(buf, nameuni, len); buf[len] = '\0'; *p_buflen = len; } @@ -3125,7 +3164,8 @@ load_next(PyObject *mod, PyObject *altmod, } if (dot != NULL) { - *p_outputname = PyUnicode_FromUnicode(dot+1, Py_UNICODE_strlen(dot+1)); + *p_outputname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + dot+1, Py_UCS4_strlen(dot+1)); if (*p_outputname == NULL) { Py_DECREF(result); return NULL; @@ -3166,7 +3206,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, Py_DECREF(item); return 0; } - if (PyUnicode_AS_UNICODE(item)[0] == '*') { + if (PyUnicode_READ_CHAR(item, 0) == '*') { PyObject *all; Py_DECREF(item); /* See if the package defines __all__ */ @@ -3304,7 +3344,7 @@ PyImport_ReloadModule(PyObject *m) PyObject *modules = PyImport_GetModuleDict(); PyObject *path_list = NULL, *loader = NULL, *existing_m = NULL; PyObject *nameobj, *bufobj, *subnameobj; - Py_UNICODE *name, *subname; + Py_UCS4 *name = NULL, *subname; struct filedescr *fdp; FILE *fp = NULL; PyObject *newm = NULL; @@ -3321,7 +3361,7 @@ PyImport_ReloadModule(PyObject *m) return NULL; } nameobj = PyModule_GetNameObject(m); - if (nameobj == NULL) + if (nameobj == NULL || PyUnicode_READY(nameobj) == -1) return NULL; if (m != PyDict_GetItem(modules, nameobj)) { PyErr_Format(PyExc_ImportError, @@ -3343,8 +3383,12 @@ PyImport_ReloadModule(PyObject *m) return NULL; } - name = PyUnicode_AS_UNICODE(nameobj); - subname = Py_UNICODE_strrchr(name, '.'); + name = PyUnicode_AsUCS4Copy(nameobj); + if (!name) { + Py_DECREF(nameobj); + return NULL; + } + subname = Py_UCS4_strrchr(name, '.'); if (subname == NULL) { Py_INCREF(nameobj); subnameobj = nameobj; @@ -3353,7 +3397,8 @@ PyImport_ReloadModule(PyObject *m) PyObject *parentname, *parent; Py_ssize_t len; len = subname - name; - parentname = PyUnicode_FromUnicode(name, len); + parentname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + name, len); if (parentname == NULL) { goto error; } @@ -3370,8 +3415,9 @@ PyImport_ReloadModule(PyObject *m) if (path_list == NULL) PyErr_Clear(); subname++; - len = PyUnicode_GET_SIZE(nameobj) - (len + 1); - subnameobj = PyUnicode_FromUnicode(subname, len); + len = PyUnicode_GET_LENGTH(nameobj) - (len + 1); + subnameobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, + subname, len); } if (subnameobj == NULL) goto error; @@ -3403,6 +3449,7 @@ PyImport_ReloadModule(PyObject *m) error: imp_modules_reloading_clear(); Py_DECREF(nameobj); + PyMem_Free(name); return newm; } @@ -3910,9 +3957,7 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) return NULL; } - cpathname = make_compiled_pathname( - PyUnicode_AS_UNICODE(pathname), - debug); + cpathname = make_compiled_pathname(pathname, debug); Py_DECREF(pathname); if (cpathname == NULL) { @@ -4105,7 +4150,7 @@ NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) &pathobj)) return -1; - if (PyUnicode_GET_SIZE(pathobj) == 0) { + if (PyUnicode_GET_LENGTH(pathobj) == 0) { PyErr_SetString(PyExc_ImportError, "empty pathname"); return -1; } diff --git a/Python/marshal.c b/Python/marshal.c index edf0366c9a..31fe66b08f 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -311,9 +311,7 @@ w_object(PyObject *v, WFILE *p) } else if (PyUnicode_CheckExact(v)) { PyObject *utf8; - utf8 = PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(v), - PyUnicode_GET_SIZE(v), - "surrogatepass"); + utf8 = PyUnicode_AsEncodedString(v, "utf8", "surrogatepass"); if (utf8 == NULL) { p->depth--; p->error = WFERR_UNMARSHALLABLE; diff --git a/Python/peephole.c b/Python/peephole.c index 705622f18e..5d536779ac 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -183,24 +183,6 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts, PyObject **ob break; case BINARY_SUBSCR: newconst = PyObject_GetItem(v, w); - /* #5057: if v is unicode, there might be differences between - wide and narrow builds in cases like '\U00012345'[0]. - Wide builds will return a non-BMP char, whereas narrow builds - will return a surrogate. In both the cases skip the - optimization in order to produce compatible pycs. - */ - if (newconst != NULL && - PyUnicode_Check(v) && PyUnicode_Check(newconst)) { - Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0]; -#ifdef Py_UNICODE_WIDE - if (ch > 0xFFFF) { -#else - if (ch >= 0xD800 && ch <= 0xDFFF) { -#endif - Py_DECREF(newconst); - return 0; - } - } break; case BINARY_LSHIFT: newconst = PyNumber_Lshift(v, w); diff --git a/Python/symtable.c b/Python/symtable.c index a0bedfc767..3578b0c692 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1525,10 +1525,10 @@ symtable_visit_alias(struct symtable *st, alias_ty a) */ PyObject *store_name; PyObject *name = (a->asname == NULL) ? a->name : a->asname; - const Py_UNICODE *base = PyUnicode_AS_UNICODE(name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) { - store_name = PyUnicode_FromUnicode(base, dot - base); + Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, + PyUnicode_GET_LENGTH(name), 1); + if (dot != -1) { + store_name = PyUnicode_Substring(name, 0, dot); if (!store_name) return 0; } diff --git a/Python/traceback.c b/Python/traceback.c index e74a1474df..9a11bf2df7 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -229,8 +229,8 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) PyObject *lineobj = NULL; PyObject *res; char buf[MAXPATHLEN+1]; - Py_UNICODE *u, *p; - Py_ssize_t len; + int kind; + void *data; /* open the file */ if (filename == NULL) @@ -285,13 +285,16 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) } /* remove the indentation of the line */ - u = PyUnicode_AS_UNICODE(lineobj); - len = PyUnicode_GET_SIZE(lineobj); - for (p=u; *p == ' ' || *p == '\t' || *p == '\014'; p++) - len--; - if (u != p) { + kind = PyUnicode_KIND(lineobj); + data = PyUnicode_DATA(lineobj); + for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) { + Py_UCS4 ch = PyUnicode_READ(kind, data, i); + if (ch != ' ' && ch != '\t' && ch != '\014') + break; + } + if (i) { PyObject *truncated; - truncated = PyUnicode_FromUnicode(p, len); + truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj)); if (truncated) { Py_DECREF(lineobj); lineobj = truncated; @@ -476,13 +479,26 @@ dump_hexadecimal(int width, unsigned long value, int fd) static void dump_ascii(int fd, PyObject *text) { + PyASCIIObject *ascii = (PyASCIIObject *)text; Py_ssize_t i, size; int truncated; - Py_UNICODE *u; - char c; - - size = PyUnicode_GET_SIZE(text); - u = PyUnicode_AS_UNICODE(text); + int kind; + void *data; + Py_UCS4 ch; + + size = ascii->length; + kind = ascii->state.kind; + if (ascii->state.compact) { + if (ascii->state.ascii) + data = ((PyASCIIObject*)text) + 1; + else + data = ((PyCompactUnicodeObject*)text) + 1; + } + else { + data = ((PyUnicodeObject *)text)->data.any; + if (data == NULL) + return; + } if (MAX_STRING_LENGTH < size) { size = MAX_STRING_LENGTH; @@ -491,27 +507,28 @@ dump_ascii(int fd, PyObject *text) else truncated = 0; - for (i=0; i < size; i++, u++) { - if (*u < 128) { - c = (char)*u; + for (i=0; i < size; i++) { + ch = PyUnicode_READ(kind, data, i); + if (ch < 128) { + char c = (char)ch; write(fd, &c, 1); } - else if (*u < 256) { + else if (ch < 256) { PUTS(fd, "\\x"); - dump_hexadecimal(2, *u, fd); + dump_hexadecimal(2, ch, fd); } else #ifdef Py_UNICODE_WIDE - if (*u < 65536) + if (ch < 65536) #endif { PUTS(fd, "\\u"); - dump_hexadecimal(4, *u, fd); + dump_hexadecimal(4, ch, fd); #ifdef Py_UNICODE_WIDE } else { PUTS(fd, "\\U"); - dump_hexadecimal(8, *u, fd); + dump_hexadecimal(8, ch, fd); #endif } } @@ -542,7 +559,7 @@ dump_frame(int fd, PyFrameObject *frame) } /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */ - lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti); + lineno = PyCode_Addr2Line(code, frame->f_lasti); PUTS(fd, ", line "); dump_decimal(fd, lineno); PUTS(fd, " in "); -- cgit v1.2.1 From 593041f3e6ac869b37c7da4355b69b1adc173b37 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 28 Sep 2011 21:49:49 +0200 Subject: Rename new macros to conform to naming rules (function macros have "Py" prefix, not "PY"). --- 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 4afdb7058c..9f38061723 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1784,7 +1784,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, return 0; len = PyUnicode_GET_LENGTH(path_unicode); - if (!PyUnicode_AsUCS4(path_unicode, buf, PY_ARRAY_LENGTH(buf), 1)) { + if (!PyUnicode_AsUCS4(path_unicode, buf, Py_ARRAY_LENGTH(buf), 1)) { Py_DECREF(path_unicode); PyErr_Clear(); return 0; @@ -1828,7 +1828,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, #endif ) buf[len++] = SEP; - if (!PyUnicode_AsUCS4(name, buf+len, PY_ARRAY_LENGTH(buf)-len, 1)) { + if (!PyUnicode_AsUCS4(name, buf+len, Py_ARRAY_LENGTH(buf)-len, 1)) { PyErr_Clear(); return 0; } @@ -2787,7 +2787,7 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, if (PyUnicode_READY(parent_name)) return NULL; buflen = PyUnicode_GET_LENGTH(parent_name); - if (!PyUnicode_AsUCS4(parent_name, buf, PY_ARRAY_LENGTH(buf), 1)) { + if (!PyUnicode_AsUCS4(parent_name, buf, Py_ARRAY_LENGTH(buf), 1)) { Py_DECREF(parent_name); PyErr_SetString(PyExc_ValueError, "Module name too long"); -- cgit v1.2.1 From fe0746fa379e590e4431680f351a4abeec232219 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Sep 2011 21:39:17 +0200 Subject: Check for PyUnicode_CopyCharacters() failure --- Python/compile.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/compile.c b/Python/compile.c index 5f03792b3e..906772289d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -245,8 +245,14 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident) return 0; /* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */ PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_'); - PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen); - PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen); + if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) { + Py_DECREF(result); + return NULL; + } + if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) { + Py_DECREF(result); + return NULL; + } return result; } -- cgit v1.2.1 From 0511538a040f2b8c33fdafcfeabf4ad8bf8ff754 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Sep 2011 21:50:16 +0200 Subject: fill_char() can now propagate an error --- Python/formatter_unicode.c | 72 ++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 25 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 9fb840b160..86385f6f7f 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -341,7 +341,7 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars, /* Pad on right. */ if (n_rpadding) - unicode_fill(s, start + nchars + n_lpadding, + unicode_fill(s, start + nchars + n_lpadding, start + nchars + n_lpadding + n_rpadding, fill_char); /* Pointer to the user content. */ @@ -501,7 +501,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, spec->n_grouped_digits = 0; else spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping( - PyUnicode_1BYTE_KIND, NULL, 0, NULL, + PyUnicode_1BYTE_KIND, NULL, 0, NULL, spec->n_digits, spec->n_min_width, locale->grouping, locale->thousands_sep); @@ -541,11 +541,12 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, /* Fill in the digit parts of a numbers's string representation, as determined in calc_number_widths(). - No error checking, since we know the buffer is the correct size. */ -static void + Return -1 on error, or 0 on success. */ +static int fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, PyObject *digits, Py_ssize_t d_start, Py_ssize_t d_end, - PyObject *prefix, Py_ssize_t p_start, Py_UCS4 fill_char, + PyObject *prefix, Py_ssize_t p_start, + Py_UCS4 fill_char, LocaleInfo *locale, int toupper) { /* Used to keep track of digits, decimal, and remainder. */ @@ -589,11 +590,8 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, char *pdigits = PyUnicode_DATA(digits); if (PyUnicode_KIND(digits) < kind) { pdigits = _PyUnicode_AsKind(digits, kind); - if (pdigits == NULL) { - /* XXX report exception */ - Py_FatalError("out of memory"); - return; - } + if (pdigits == NULL) + return -1; } #ifndef NDEBUG r = @@ -640,6 +638,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, unicode_fill(out, pos, pos + spec->n_rpadding, fill_char); pos += spec->n_rpadding; } + return 0; } static char no_grouping[1] = {CHAR_MAX}; @@ -765,6 +764,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, Py_ssize_t prefix; NumberFieldWidths spec; long x; + int err; /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ @@ -886,10 +886,13 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, goto done; /* Populate the memory. */ - fill_number(result, 0, &spec, tmp, inumeric_chars, inumeric_chars + n_digits, - tmp, prefix, - format->fill_char == '\0' ? ' ' : format->fill_char, - &locale, format->type == 'X'); + err = fill_number(result, 0, &spec, + tmp, inumeric_chars, inumeric_chars + n_digits, + tmp, prefix, + format->fill_char == '\0' ? ' ' : format->fill_char, + &locale, format->type == 'X'); + if (err) + Py_CLEAR(result); done: Py_XDECREF(tmp); @@ -929,6 +932,7 @@ format_float_internal(PyObject *value, Py_UCS4 sign_char = '\0'; int float_type; /* Used to see if we have a nan, inf, or regular float. */ PyObject *unicode_tmp = NULL; + int err; /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ @@ -1010,7 +1014,7 @@ format_float_internal(PyObject *value, &locale); /* Calculate how much memory we'll need. */ - n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, + n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, index + n_digits, n_remainder, has_decimal, &locale, format); @@ -1020,10 +1024,13 @@ format_float_internal(PyObject *value, goto done; /* Populate the memory. */ - fill_number(result, 0, &spec, unicode_tmp, index, index + n_digits, - NULL, 0, - format->fill_char == '\0' ? ' ' : format->fill_char, &locale, - 0); + err = fill_number(result, 0, &spec, + unicode_tmp, index, index + n_digits, + NULL, 0, + format->fill_char == '\0' ? ' ' : format->fill_char, + &locale, 0); + if (err) + Py_CLEAR(result); done: PyMem_Free(buf); @@ -1077,6 +1084,7 @@ format_complex_internal(PyObject *value, Py_ssize_t total; PyObject *re_unicode_tmp = NULL; PyObject *im_unicode_tmp = NULL; + int err; /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ @@ -1170,9 +1178,9 @@ format_complex_internal(PyObject *value, /* Determine if we have any "remainder" (after the digits, might include decimal or exponent or both (or neither)) */ - parse_number(re_unicode_tmp, i_re, i_re + n_re_digits, + parse_number(re_unicode_tmp, i_re, i_re + n_re_digits, &n_re_remainder, &re_has_decimal); - parse_number(im_unicode_tmp, i_im, i_im + n_im_digits, + parse_number(im_unicode_tmp, i_im, i_im + n_im_digits, &n_im_remainder, &im_has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ @@ -1225,12 +1233,26 @@ format_complex_internal(PyObject *value, PyUnicode_WRITE(rkind, rdata, index++, '('); if (!skip_re) { - fill_number(result, index, &re_spec, re_unicode_tmp, - i_re, i_re + n_re_digits, NULL, 0, 0, &locale, 0); + err = fill_number(result, index, &re_spec, + re_unicode_tmp, i_re, i_re + n_re_digits, + NULL, 0, + 0, + &locale, 0); + if (err) { + Py_CLEAR(result); + goto done; + } index += n_re_total; } - fill_number(result, index, &im_spec, im_unicode_tmp, - i_im, i_im + n_im_digits, NULL, 0, 0, &locale, 0); + err = fill_number(result, index, &im_spec, + im_unicode_tmp, i_im, i_im + n_im_digits, + NULL, 0, + 0, + &locale, 0); + if (err) { + Py_CLEAR(result); + goto done; + } index += n_im_total; PyUnicode_WRITE(rkind, rdata, index++, 'j'); -- cgit v1.2.1 From 895a5d4f7037dfc0563aa482d07b5d32b5dca481 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Sep 2011 21:50:42 +0200 Subject: fill_number() ensures that the 'digits' string is ready --- Python/formatter_unicode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 86385f6f7f..52ccafa8d0 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -587,7 +587,10 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, /* Only for type 'c' special case, it has no digits. */ if (spec->n_digits != 0) { /* Fill the digits with InsertThousandsGrouping. */ - char *pdigits = PyUnicode_DATA(digits); + char *pdigits; + if (PyUnicode_READY(digits)) + return -1; + pdigits = PyUnicode_DATA(digits); if (PyUnicode_KIND(digits) < kind) { pdigits = _PyUnicode_AsKind(digits, kind); if (pdigits == NULL) -- cgit v1.2.1 From 5afe8babef534ce040e31ce8d000ce622a3366c7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 28 Sep 2011 21:53:49 +0200 Subject: fill_number() and format_string_internal() check for PyUnicode_CopyCharacters() failure --- Python/formatter_unicode.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 52ccafa8d0..609df648b0 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -566,7 +566,10 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, PyUnicode_WRITE(kind, data, pos++, spec->sign); } if (spec->n_prefix) { - PyUnicode_CopyCharacters(out, pos, prefix, p_start, spec->n_prefix); + if (PyUnicode_CopyCharacters(out, pos, + prefix, p_start, + spec->n_prefix) < 0) + return -1; if (toupper) { Py_ssize_t t; /* XXX if the upper-case prefix is wider than the target @@ -632,7 +635,8 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, } if (spec->n_remainder) { - PyUnicode_CopyCharacters(out, pos, digits, d_pos, spec->n_remainder); + if (PyUnicode_CopyCharacters(out, pos, digits, d_pos, spec->n_remainder) < 0) + return -1; pos += spec->n_remainder; d_pos += spec->n_remainder; } @@ -735,7 +739,8 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format) lpad, rpad); /* Then the source string. */ - PyUnicode_CopyCharacters(result, pos, value, 0, len); + if (PyUnicode_CopyCharacters(result, pos, value, 0, len) < 0) + Py_CLEAR(result); done: return result; -- cgit v1.2.1 From 2319ec2bcccdc5b2e8e051323423d9e4f96853c8 Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Thu, 29 Sep 2011 00:18:19 +0300 Subject: #13054: sys.maxunicode is now always 0x10FFFF. --- Python/sysmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index b549203536..dea21490e2 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1261,7 +1261,7 @@ 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\ +maxunicode -- the value of the largest Unicode codepoint\n\ platform -- platform identifier\n\ prefix -- prefix used to find the Python library\n\ thread_info -- a struct sequence with information about the thread implementation.\n\ @@ -1536,7 +1536,7 @@ _PySys_Init(void) SET_SYS_FROM_STRING("hash_info", get_hash_info()); SET_SYS_FROM_STRING("maxunicode", - PyLong_FromLong(PyUnicode_GetMax())); + PyLong_FromLong(0x10FFFF)); SET_SYS_FROM_STRING("builtin_module_names", list_builtin_module_names()); { -- cgit v1.2.1 From 687c3b16f72a6b2b64971c1c27e33e27f001ede8 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 29 Sep 2011 00:42:28 +0200 Subject: Use the new Py_ARRAY_LENGTH macro --- Python/codecs.c | 2 +- Python/dynload_aix.c | 3 +-- Python/sysmodule.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index be2e8334c6..4c2fc5d722 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -1044,7 +1044,7 @@ static int _PyCodecRegistry_Init(void) interp->codec_error_registry = PyDict_New(); if (interp->codec_error_registry) { - for (i = 0; i < sizeof(methods)/sizeof(methods[0]); ++i) { + for (i = 0; i < Py_ARRAY_LENGTH(methods); ++i) { PyObject *func = PyCFunction_New(&methods[i].def, NULL); int res; if (!func) diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c index 74c7b32603..6287c86edf 100644 --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -129,7 +129,6 @@ aix_loaderror(const char *pathname) {L_ERROR_ERRNO, NULL} }; -#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) #define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) PyOS_snprintf(errbuf, sizeof(errbuf), "from module %.200s ", pathname); @@ -140,7 +139,7 @@ aix_loaderror(const char *pathname) } for(i = 0; message[i] && *message[i]; i++) { int nerr = atoi(message[i]); - for (j=0; j Date: Thu, 29 Sep 2011 04:01:43 +0200 Subject: modsupport.c reuses Py_UNICODE_strlen() --- Python/modsupport.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/modsupport.c b/Python/modsupport.c index 08f5065883..428914f378 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -148,15 +148,6 @@ do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags) return v; } -static int -_ustrlen(Py_UNICODE *u) -{ - int i = 0; - Py_UNICODE *v = u; - while (*v != 0) { i++; v++; } - return i; -} - static PyObject * do_mktuple(const char **p_format, va_list *p_va, int endchar, int n, int flags) { @@ -269,7 +260,7 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) } else { if (n < 0) - n = _ustrlen(u); + n = Py_UNICODE_strlen(u); v = PyUnicode_FromUnicode(u, n); } return v; -- cgit v1.2.1 From 3238a6809400acc13c558cff1c184e58fcf92d9c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 1 Oct 2011 01:26:08 +0200 Subject: Remove commented code: str+=str is no more super-optimized --- Python/ceval.c | 118 +++------------------------------------------------------ 1 file changed, 6 insertions(+), 112 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 0a346f4179..f6f422ee32 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -136,8 +136,6 @@ static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); -static PyObject * unicode_concatenate(PyObject *, PyObject *, - PyFrameObject *, unsigned char *); static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ @@ -1509,17 +1507,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_vx; - } - else { + if (PyUnicode_Check(v) && PyUnicode_Check(w)) + x = PyUnicode_Concat(v, w); + else x = PyNumber_Add(v, w); - } Py_DECREF(v); - skip_decref_vx: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -1670,17 +1662,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_v; - } - else { + if (PyUnicode_Check(v) && PyUnicode_Check(w)) + x = PyUnicode_Concat(v, w); + else x = PyNumber_InPlaceAdd(v, w); - } Py_DECREF(v); - skip_decref_v: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -4515,98 +4501,6 @@ format_exc_unbound(PyCodeObject *co, int oparg) } } -static PyObject * -unicode_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) -{ - /* This function implements 'variable += expr' when both arguments - are (Unicode) strings. */ - - w = PyUnicode_Concat(v, w); - Py_DECREF(v); - return w; - - /* XXX: This optimization is currently disabled as unicode objects in the - new flexible representation are not in-place resizable anymore. */ -#if 0 - Py_ssize_t v_len = PyUnicode_GET_SIZE(v); - Py_ssize_t w_len = PyUnicode_GET_SIZE(w); - Py_ssize_t new_len = v_len + w_len; - if (new_len < 0) { - PyErr_SetString(PyExc_OverflowError, - "strings are too large to concat"); - return NULL; - } - - if (Py_REFCNT(v) == 2) { - /* In the common case, there are 2 references to the value - * stored in 'variable' when the += is performed: one on the - * value stack (in 'v') and one still stored in the - * 'variable'. We try to delete the variable now to reduce - * the refcnt to 1. - */ - switch (*next_instr) { - case STORE_FAST: - { - int oparg = PEEKARG(); - PyObject **fastlocals = f->f_localsplus; - if (GETLOCAL(oparg) == v) - SETLOCAL(oparg, NULL); - break; - } - case STORE_DEREF: - { - PyObject **freevars = (f->f_localsplus + - f->f_code->co_nlocals); - PyObject *c = freevars[PEEKARG()]; - if (PyCell_GET(c) == v) - PyCell_Set(c, NULL); - break; - } - case STORE_NAME: - { - PyObject *names = f->f_code->co_names; - PyObject *name = GETITEM(names, PEEKARG()); - PyObject *locals = f->f_locals; - if (PyDict_CheckExact(locals) && - PyDict_GetItem(locals, name) == v) { - if (PyDict_DelItem(locals, name) != 0) { - PyErr_Clear(); - } - } - break; - } - } - } - - if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v) && - !PyUnicode_IS_COMPACT((PyUnicodeObject *)v)) { - /* Now we own the last reference to 'v', so we can resize it - * in-place. - */ - if (PyUnicode_Resize(&v, new_len) != 0) { - /* XXX if PyUnicode_Resize() fails, 'v' has been - * deallocated so it cannot be put back into - * 'variable'. The MemoryError is raised when there - * is no value in 'variable', which might (very - * remotely) be a cause of incompatibilities. - */ - return NULL; - } - /* copy 'w' into the newly allocated area of 'v' */ - memcpy(PyUnicode_AS_UNICODE(v) + v_len, - PyUnicode_AS_UNICODE(w), w_len*sizeof(Py_UNICODE)); - return v; - } - else { - /* When in-place resizing is not an option. */ - w = PyUnicode_Concat(v, w); - Py_DECREF(v); - return w; - } -#endif -} - #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject * -- cgit v1.2.1 From cd6c51adb67b308df10d175f2e1afc94d8742e1b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 30 Sep 2011 21:31:21 -0400 Subject: remove "fast-path" for (i)adding strings These were just an artifact of the old unicode concatenation hack and likely just penalized other kinds of adding. Also, this fixes __(i)add__ on string subclasses. --- Python/ceval.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index f6f422ee32..870d19d55c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1507,10 +1507,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - if (PyUnicode_Check(v) && PyUnicode_Check(w)) - x = PyUnicode_Concat(v, w); - else - x = PyNumber_Add(v, w); + x = PyNumber_Add(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); @@ -1662,10 +1659,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - if (PyUnicode_Check(v) && PyUnicode_Check(w)) - x = PyUnicode_Concat(v, w); - else - x = PyNumber_InPlaceAdd(v, w); + x = PyNumber_InPlaceAdd(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); -- cgit v1.2.1 From 2ab1e534bf781097c59588983df13f737c912576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sat, 1 Oct 2011 16:35:40 +0200 Subject: Issue 13085: Fix some memory leaks. Patch by Stefan Krah. --- Python/import.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 9f38061723..901b733480 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1564,8 +1564,10 @@ get_sourcefile(PyObject *filename) if (py == NULL) goto error; - if (_Py_stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) + if (_Py_stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + PyMem_Free(fileuni); return py; + } Py_DECREF(py); goto unchanged; @@ -3074,7 +3076,7 @@ load_next(PyObject *mod, PyObject *altmod, Py_ssize_t len; Py_UCS4 *p; PyObject *fullname, *name, *result, *mark_name; - const Py_UCS4 *nameuni; + Py_UCS4 *nameuni; *p_outputname = NULL; @@ -3095,7 +3097,7 @@ load_next(PyObject *mod, PyObject *altmod, if (len == 0) { PyErr_SetString(PyExc_ValueError, "Empty module name"); - return NULL; + goto error; } } else @@ -3104,7 +3106,7 @@ load_next(PyObject *mod, PyObject *altmod, if (*p_buflen+len+1 >= bufsize) { PyErr_SetString(PyExc_ValueError, "Module name too long"); - return NULL; + goto error; } p = buf + *p_buflen; @@ -3119,12 +3121,12 @@ load_next(PyObject *mod, PyObject *altmod, fullname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, *p_buflen); if (fullname == NULL) - return NULL; + goto error; name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, p, len); if (name == NULL) { Py_DECREF(fullname); - return NULL; + goto error; } result = import_submodule(mod, name, fullname); Py_DECREF(fullname); @@ -3138,12 +3140,12 @@ load_next(PyObject *mod, PyObject *altmod, buf, *p_buflen); if (mark_name == NULL) { Py_DECREF(result); - return NULL; + goto error; } if (mark_miss(mark_name) != 0) { Py_DECREF(result); Py_DECREF(mark_name); - return NULL; + goto error; } Py_DECREF(mark_name); Py_UCS4_strncpy(buf, nameuni, len); @@ -3154,13 +3156,13 @@ load_next(PyObject *mod, PyObject *altmod, else Py_DECREF(name); if (result == NULL) - return NULL; + goto error; if (result == Py_None) { Py_DECREF(result); PyErr_Format(PyExc_ImportError, "No module named %R", inputname); - return NULL; + goto error; } if (dot != NULL) { @@ -3168,11 +3170,17 @@ load_next(PyObject *mod, PyObject *altmod, dot+1, Py_UCS4_strlen(dot+1)); if (*p_outputname == NULL) { Py_DECREF(result); - return NULL; + goto error; } } +out: + PyMem_Free(nameuni); return result; + +error: + PyMem_Free(nameuni); + return NULL; } static int -- cgit v1.2.1 From 7a98f5f5ced85e78dc79169bfaeaa1b3adfa0596 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 2 Oct 2011 13:19:16 -0400 Subject: remove unused label --- Python/import.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 901b733480..9f094c0da0 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3174,7 +3174,6 @@ load_next(PyObject *mod, PyObject *altmod, } } -out: PyMem_Free(nameuni); return result; -- cgit v1.2.1 From ca68997fb8ada5c2a95caaf984f29bf02732336a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 2 Oct 2011 19:00:15 +0200 Subject: PyCodec_ReplaceErrors() uses "C" format instead of "u#" to build result --- Python/codecs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 4c2fc5d722..0008bdcbdc 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -534,10 +534,11 @@ PyObject *PyCodec_ReplaceErrors(PyObject *exc) return Py_BuildValue("(Nn)", res, end); } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { - Py_UNICODE res = Py_UNICODE_REPLACEMENT_CHARACTER; if (PyUnicodeDecodeError_GetEnd(exc, &end)) return NULL; - return Py_BuildValue("(u#n)", &res, 1, end); + return Py_BuildValue("(Cn)", + (int)Py_UNICODE_REPLACEMENT_CHARACTER, + end); } else if (PyObject_IsInstance(exc, PyExc_UnicodeTranslateError)) { PyObject *res; -- cgit v1.2.1 From 0c2e8df558514b8e0d85d011857f3c2984e39f6e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 2 Oct 2011 20:35:10 +0200 Subject: Check error when calling PyUnicode_AppendAndDel() --- Python/dynload_win.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 932a637680..c620e58948 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -187,7 +187,7 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, HINSTANCE hDLL = NULL; unsigned int old_mode; ULONG_PTR cookie = 0; - + /* Don't display a message box when Python can't load a DLL */ old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); @@ -248,8 +248,10 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, theInfo, theLength)); } - PyErr_SetObject(PyExc_ImportError, message); - Py_XDECREF(message); + if (message != NULL) { + PyErr_SetObject(PyExc_ImportError, message); + Py_DECREF(message); + } return NULL; } else { char buffer[256]; -- cgit v1.2.1 From a8b8005d1149e2f94427ba5684f1684f9ff7971e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 2 Oct 2011 20:34:20 +0200 Subject: ceval.c: restore str+=str optimization --- Python/ceval.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 870d19d55c..686a54dafe 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -136,6 +136,8 @@ static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); +static PyObject * unicode_concatenate(PyObject *, PyObject *, + PyFrameObject *, unsigned char *); static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ @@ -1507,8 +1509,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - x = PyNumber_Add(v, w); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_vx; + } + else { + x = PyNumber_Add(v, w); + } Py_DECREF(v); + skip_decref_vx: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -1659,8 +1670,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - x = PyNumber_InPlaceAdd(v, w); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_v; + } + else { + x = PyNumber_InPlaceAdd(v, w); + } Py_DECREF(v); + skip_decref_v: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -3399,7 +3419,7 @@ save_exc_state(PyThreadState *tstate, PyFrameObject *f) f->f_exc_traceback = tstate->exc_traceback; Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); + Py_XDECREF(traceback); } static void @@ -4495,6 +4515,56 @@ format_exc_unbound(PyCodeObject *co, int oparg) } } +static PyObject * +unicode_concatenate(PyObject *v, PyObject *w, + PyFrameObject *f, unsigned char *next_instr) +{ + PyObject *res; + if (Py_REFCNT(v) == 2) { + /* In the common case, there are 2 references to the value + * stored in 'variable' when the += is performed: one on the + * value stack (in 'v') and one still stored in the + * 'variable'. We try to delete the variable now to reduce + * the refcnt to 1. + */ + switch (*next_instr) { + case STORE_FAST: + { + int oparg = PEEKARG(); + PyObject **fastlocals = f->f_localsplus; + if (GETLOCAL(oparg) == v) + SETLOCAL(oparg, NULL); + break; + } + case STORE_DEREF: + { + PyObject **freevars = (f->f_localsplus + + f->f_code->co_nlocals); + PyObject *c = freevars[PEEKARG()]; + if (PyCell_GET(c) == v) + PyCell_Set(c, NULL); + break; + } + case STORE_NAME: + { + PyObject *names = f->f_code->co_names; + PyObject *name = GETITEM(names, PEEKARG()); + PyObject *locals = f->f_locals; + if (PyDict_CheckExact(locals) && + PyDict_GetItem(locals, name) == v) { + if (PyDict_DelItem(locals, name) != 0) { + PyErr_Clear(); + } + } + break; + } + } + } + res = v; + PyUnicode_Append(&res, w); + return res; +} + #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject * -- cgit v1.2.1 From 00c5b764e1936139724dd9970fb509f3c2ab1eb2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 4 Oct 2011 20:53:03 +0200 Subject: Fix usage og PyUnicode_READY() --- Python/getargs.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 0e7d9c4350..2c2db36193 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -834,14 +834,21 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'C': {/* unicode char */ int *p = va_arg(*p_va, int *); - if (PyUnicode_Check(arg) && - PyUnicode_GET_LENGTH(arg) == 1) { - int kind = PyUnicode_KIND(arg); - void *data = PyUnicode_DATA(arg); - *p = PyUnicode_READ(kind, data, 0); - } - else + int kind; + void *data; + + if (!PyUnicode_Check(arg)) + return converterr("a unicode character", arg, msgbuf, bufsize); + + if (PyUnicode_READY(arg)) + RETURN_ERR_OCCURRED; + + if (PyUnicode_GET_LENGTH(arg) != 1) return converterr("a unicode character", arg, msgbuf, bufsize); + + kind = PyUnicode_KIND(arg); + data = PyUnicode_DATA(arg); + *p = PyUnicode_READ(kind, data, 0); break; } -- cgit v1.2.1 From 4cea3a5c83fca73972f3cf75b9688542b85c4042 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 5 Oct 2011 21:24:08 +0200 Subject: Add asciilib: similar to ucs1, ucs2 and ucs4 library, but specialized to ASCII ucs1, ucs2 and ucs4 libraries have to scan created substring to find the maximum character, whereas it is not need to ASCII strings. Because ASCII strings are common, it is useful to optimize ASCII. --- Python/formatter_unicode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 609df648b0..c989d83654 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -501,7 +501,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, spec->n_grouped_digits = 0; else spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping( - PyUnicode_1BYTE_KIND, NULL, 0, NULL, + NULL, PyUnicode_1BYTE_KIND, NULL, 0, NULL, spec->n_digits, spec->n_min_width, locale->grouping, locale->thousands_sep); @@ -603,7 +603,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, r = #endif _PyUnicode_InsertThousandsGrouping( - kind, + out, kind, (char*)data + PyUnicode_KIND_SIZE(kind, pos), spec->n_grouped_digits, pdigits + PyUnicode_KIND_SIZE(kind, d_pos), -- cgit v1.2.1 From dc2d990c5a49d8a3c852444d37e59a1408ac326c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 5 Oct 2011 22:44:12 +0200 Subject: traceback: fix dump_ascii() for string with kind=PyUnicode_WCHAR_KIND --- Python/traceback.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/traceback.c b/Python/traceback.c index 9a11bf2df7..b66c96cda6 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -483,7 +483,8 @@ dump_ascii(int fd, PyObject *text) Py_ssize_t i, size; int truncated; int kind; - void *data; + void *data = NULL; + wchar_t *wstr = NULL; Py_UCS4 ch; size = ascii->length; @@ -494,11 +495,17 @@ dump_ascii(int fd, PyObject *text) else data = ((PyCompactUnicodeObject*)text) + 1; } - else { + else if (kind != PyUnicode_WCHAR_KIND) { data = ((PyUnicodeObject *)text)->data.any; if (data == NULL) return; } + else { + wstr = ((PyASCIIObject *)text)->wstr; + if (wstr == NULL) + return; + size = ((PyCompactUnicodeObject *)text)->wstr_length; + } if (MAX_STRING_LENGTH < size) { size = MAX_STRING_LENGTH; @@ -508,7 +515,10 @@ dump_ascii(int fd, PyObject *text) truncated = 0; for (i=0; i < size; i++) { - ch = PyUnicode_READ(kind, data, i); + if (kind != PyUnicode_WCHAR_KIND) + ch = PyUnicode_READ(kind, data, i); + else + ch = wstr[i]; if (ch < 128) { char c = (char)ch; write(fd, &c, 1); -- cgit v1.2.1 From 7cba64b1d6dd00da0c98fceaac11e3fc7086c852 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 6 Oct 2011 01:45:57 +0200 Subject: Don't check for the maximum character when copying from unicodeobject.c * Create copy_characters() function which doesn't check for the maximum character in release mode * _PyUnicode_CheckConsistency() is no more static to be able to use it in _PyUnicode_FormatAdvanced() (in formatter_unicode.c) * _PyUnicode_CheckConsistency() checks the string hash --- Python/formatter_unicode.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index c989d83654..a389734390 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -1284,33 +1284,31 @@ _PyUnicode_FormatAdvanced(PyObject *obj, Py_ssize_t start, Py_ssize_t end) { InternalFormatSpec format; - PyObject *result = NULL; + PyObject *result; /* check for the special case of zero length format spec, make it equivalent to str(obj) */ - if (start == end) { - result = PyObject_Str(obj); - goto done; - } + if (start == end) + return PyObject_Str(obj); /* parse the format_spec */ if (!parse_internal_render_format_spec(format_spec, start, end, &format, 's', '<')) - goto done; + return NULL; /* type conversion? */ switch (format.type) { case 's': /* no type conversion needed, already a string. do the formatting */ result = format_string_internal(obj, &format); + if (result != NULL) + assert(_PyUnicode_CheckConsistency(result, 1)); break; default: /* unknown */ unknown_presentation_type(format.type, obj->ob_type->tp_name); - goto done; + result = NULL; } - -done: return result; } -- cgit v1.2.1 From 9146424d4d60bd9f2db88362ca1c3b069f966730 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 6 Oct 2011 02:34:51 +0200 Subject: Fix _warnings.c: make the filename string ready --- Python/_warnings.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 2bcca91fa6..792e3ed6df 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -497,9 +497,16 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, /* Setup filename. */ *filename = PyDict_GetItemString(globals, "__file__"); if (*filename != NULL && PyUnicode_Check(*filename)) { - Py_ssize_t len = PyUnicode_GetSize(*filename); - int kind = PyUnicode_KIND(*filename); - void *data = PyUnicode_DATA(*filename); + Py_ssize_t len; + int kind; + void *data; + + if (PyUnicode_READY(*filename)) + goto handle_error; + + len = PyUnicode_GetSize(*filename); + kind = PyUnicode_KIND(*filename); + data = PyUnicode_DATA(*filename); /* if filename.lower().endswith((".pyc", ".pyo")): */ if (len >= 4 && -- cgit v1.2.1 From 0aeb34c31cc7bfc0c0fd5595b017e3f9dc0a93ef Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 6 Oct 2011 02:39:42 +0200 Subject: Fix find_module_path(): make the string ready --- Python/import.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 9f094c0da0..5f84ac2f74 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1785,6 +1785,9 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, else return 0; + if (PyUnicode_READY(path_unicode)) + return -1; + len = PyUnicode_GET_LENGTH(path_unicode); if (!PyUnicode_AsUCS4(path_unicode, buf, Py_ARRAY_LENGTH(buf), 1)) { Py_DECREF(path_unicode); -- cgit v1.2.1 From 631b94c03720b2c23e0098dfae52fed6526c6782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 7 Oct 2011 20:55:35 +0200 Subject: Change PyUnicode_KIND to 1,2,4. Drop _KIND_SIZE and _CHARACTER_SIZE. --- Python/formatter_unicode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index a389734390..037880068a 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -604,9 +604,9 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, #endif _PyUnicode_InsertThousandsGrouping( out, kind, - (char*)data + PyUnicode_KIND_SIZE(kind, pos), + (char*)data + kind * pos, spec->n_grouped_digits, - pdigits + PyUnicode_KIND_SIZE(kind, d_pos), + pdigits + kind * d_pos, spec->n_digits, spec->n_min_width, locale->grouping, locale->thousands_sep); #ifndef NDEBUG -- cgit v1.2.1 From dcacb24f386ae1b107462181af42b6826ec15fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 9 Oct 2011 10:38:36 +0200 Subject: =?UTF-8?q?Add=20API=20for=20static=20strings,=20primarily=20good?= =?UTF-8?q?=20for=20identifiers.=20Thanks=20to=20Konrad=20Sch=C3=B6bel=20a?= =?UTF-8?q?nd=20Jasper=20Schulz=20for=20helping=20with=20the=20mass-editin?= =?UTF-8?q?g.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Python/_warnings.c | 3 ++- Python/ast.c | 3 ++- Python/bltinmodule.c | 13 ++++++++----- Python/ceval.c | 3 ++- Python/import.c | 11 +++++++---- Python/marshal.c | 11 ++++++++--- Python/pythonrun.c | 30 ++++++++++++++++++------------ Python/sysmodule.c | 3 ++- Python/traceback.c | 12 ++++++++---- 9 files changed, 57 insertions(+), 32 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 792e3ed6df..e5631079a9 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -18,11 +18,12 @@ static int check_matched(PyObject *obj, PyObject *arg) { PyObject *result; + _Py_identifier(match); int rc; if (obj == Py_None) return 1; - result = PyObject_CallMethod(obj, "match", "O", arg); + result = _PyObject_CallMethodId(obj, &PyId_match, "O", arg); if (result == NULL) return -1; diff --git a/Python/ast.c b/Python/ast.c index a52fd093e6..987297924e 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -527,6 +527,7 @@ static PyObject *parsestrplus(struct compiling *, const node *n, static identifier new_identifier(const char* n, PyArena *arena) { + _Py_identifier(normalize); PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); if (!id || PyUnicode_READY(id) == -1) return NULL; @@ -537,7 +538,7 @@ new_identifier(const char* n, PyArena *arena) PyObject *id2; if (!m) return NULL; - id2 = PyObject_CallMethod(m, "normalize", "sO", "NFKC", id); + id2 = _PyObject_CallMethodId(m, &PyId_normalize, "sO", "NFKC", id); Py_DECREF(m); if (!id2) return NULL; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 04f5231891..c174e9d5ef 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -32,6 +32,9 @@ const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; #endif +_Py_identifier(fileno); +_Py_identifier(flush); + static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) { @@ -1567,7 +1570,7 @@ builtin_input(PyObject *self, PyObject *args) } /* First of all, flush stderr */ - tmp = PyObject_CallMethod(ferr, "flush", ""); + tmp = _PyObject_CallMethodId(ferr, &PyId_flush, ""); if (tmp == NULL) PyErr_Clear(); else @@ -1576,7 +1579,7 @@ builtin_input(PyObject *self, PyObject *args) /* We should only use (GNU) readline if Python's sys.stdin and sys.stdout are the same as C's stdin and stdout, because we need to pass it those. */ - tmp = PyObject_CallMethod(fin, "fileno", ""); + tmp = _PyObject_CallMethodId(fin, &PyId_fileno, ""); if (tmp == NULL) { PyErr_Clear(); tty = 0; @@ -1589,7 +1592,7 @@ builtin_input(PyObject *self, PyObject *args) tty = fd == fileno(stdin) && isatty(fd); } if (tty) { - tmp = PyObject_CallMethod(fout, "fileno", ""); + tmp = _PyObject_CallMethodId(fout, &PyId_fileno, ""); if (tmp == NULL) PyErr_Clear(); else { @@ -1621,7 +1624,7 @@ builtin_input(PyObject *self, PyObject *args) Py_DECREF(stdin_encoding); return NULL; } - tmp = PyObject_CallMethod(fout, "flush", ""); + tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); if (tmp == NULL) PyErr_Clear(); else @@ -1703,7 +1706,7 @@ builtin_input(PyObject *self, PyObject *args) if (PyFile_WriteObject(promptarg, fout, Py_PRINT_RAW) != 0) return NULL; } - tmp = PyObject_CallMethod(fout, "flush", ""); + tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); if (tmp == NULL) PyErr_Clear(); else diff --git a/Python/ceval.c b/Python/ceval.c index 686a54dafe..04d3df1500 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -372,6 +372,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) void PyEval_ReInitThreads(void) { + _Py_identifier(_after_fork); PyObject *threading, *result; PyThreadState *tstate = PyThreadState_GET(); @@ -392,7 +393,7 @@ PyEval_ReInitThreads(void) PyErr_Clear(); return; } - result = PyObject_CallMethod(threading, "_after_fork", NULL); + result = _PyObject_CallMethodId(threading, &PyId__after_fork, NULL); if (result == NULL) PyErr_WriteUnraisable(threading); else diff --git a/Python/import.c b/Python/import.c index 5f84ac2f74..6eca90a0f7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1801,6 +1801,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, /* sys.path_hooks import hook */ if (p_loader != NULL) { + _Py_identifier(find_module); PyObject *importer; importer = get_path_importer(path_importer_cache, @@ -1811,8 +1812,8 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, /* Note: importer is a borrowed reference */ if (importer != Py_None) { PyObject *loader; - loader = PyObject_CallMethod(importer, - "find_module", "O", fullname); + loader = _PyObject_CallMethodId(importer, + &PyId_find_module, "O", fullname); if (loader == NULL) return -1; /* error */ if (loader != Py_None) { @@ -2030,6 +2031,7 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, /* sys.meta_path import hook */ if (p_loader != NULL) { + _Py_identifier(find_module); PyObject *meta_path; meta_path = PySys_GetObject("meta_path"); @@ -2044,7 +2046,7 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, for (i = 0; i < npath; i++) { PyObject *loader; PyObject *hook = PyList_GetItem(meta_path, i); - loader = PyObject_CallMethod(hook, "find_module", + loader = _PyObject_CallMethodId(hook, &PyId_find_module, "OO", fullname, search_path_list != NULL ? search_path_list : Py_None); @@ -2454,12 +2456,13 @@ load_module(PyObject *name, FILE *fp, PyObject *pathname, int type, PyObject *lo break; case IMP_HOOK: { + _Py_identifier(load_module); if (loader == NULL) { PyErr_SetString(PyExc_ImportError, "import hook without loader"); return NULL; } - m = PyObject_CallMethod(loader, "load_module", "O", name); + m = _PyObject_CallMethodId(loader, &PyId_load_module, "O", name); break; } diff --git a/Python/marshal.c b/Python/marshal.c index 31fe66b08f..b8288d0c1a 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -480,7 +480,9 @@ r_string(char *s, int n, RFILE *p) } } else { - PyObject *data = PyObject_CallMethod(p->readable, "read", "i", n); + _Py_identifier(read); + + PyObject *data = _PyObject_CallMethodId(p->readable, &PyId_read, "i", n); read = 0; if (data != NULL) { if (!PyBytes_Check(data)) { @@ -1290,12 +1292,14 @@ marshal_dump(PyObject *self, PyObject *args) int version = Py_MARSHAL_VERSION; PyObject *s; PyObject *res; + _Py_identifier(write); + if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) return NULL; s = PyMarshal_WriteObjectToString(x, version); if (s == NULL) return NULL; - res = PyObject_CallMethod(f, "write", "O", s); + res = _PyObject_CallMethodId(f, &PyId_write, "O", s); Py_DECREF(s); return res; } @@ -1317,6 +1321,7 @@ static PyObject * marshal_load(PyObject *self, PyObject *f) { PyObject *data, *result; + _Py_identifier(read); RFILE rf; /* @@ -1324,7 +1329,7 @@ marshal_load(PyObject *self, PyObject *f) * This is to ensure that the object passed in at least * has a read method which returns bytes. */ - data = PyObject_CallMethod(f, "read", "i", 0); + data = _PyObject_CallMethodId(f, &PyId_read, "i", 0); if (data == NULL) return NULL; if (!PyBytes_Check(data)) { diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 1888fba9b9..0ef36bbb8c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -352,9 +352,10 @@ flush_std_files(void) PyObject *fout = PySys_GetObject("stdout"); PyObject *ferr = PySys_GetObject("stderr"); PyObject *tmp; + _Py_identifier(flush); if (fout != NULL && fout != Py_None) { - tmp = PyObject_CallMethod(fout, "flush", ""); + tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); if (tmp == NULL) PyErr_WriteUnraisable(fout); else @@ -362,7 +363,7 @@ flush_std_files(void) } if (ferr != NULL && ferr != Py_None) { - tmp = PyObject_CallMethod(ferr, "flush", ""); + tmp = _PyObject_CallMethodId(ferr, &PyId_flush, ""); if (tmp == NULL) PyErr_Clear(); else @@ -805,6 +806,9 @@ create_stdio(PyObject* io, const char* newline; PyObject *line_buffering; int buffering, isatty; + _Py_identifier(open); + _Py_identifier(isatty); + _Py_identifier(TextIOWrapper); /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper @@ -819,9 +823,9 @@ create_stdio(PyObject* io, mode = "wb"; else mode = "rb"; - buf = PyObject_CallMethod(io, "open", "isiOOOi", - fd, mode, buffering, - Py_None, Py_None, Py_None, 0); + buf = _PyObject_CallMethodId(io, &PyId_open, "isiOOOi", + fd, mode, buffering, + Py_None, Py_None, Py_None, 0); if (buf == NULL) goto error; @@ -838,7 +842,7 @@ create_stdio(PyObject* io, text = PyUnicode_FromString(name); if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) goto error; - res = PyObject_CallMethod(raw, "isatty", ""); + res = _PyObject_CallMethodId(raw, &PyId_isatty, ""); if (res == NULL) goto error; isatty = PyObject_IsTrue(res); @@ -861,9 +865,9 @@ create_stdio(PyObject* io, } #endif - stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO", - buf, encoding, errors, - newline, line_buffering); + stream = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "OsssO", + buf, encoding, errors, + newline, line_buffering); Py_CLEAR(buf); if (stream == NULL) goto error; @@ -1759,13 +1763,14 @@ flush_io(void) { PyObject *f, *r; PyObject *type, *value, *traceback; + _Py_identifier(flush); /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); f = PySys_GetObject("stderr"); if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); + r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) Py_DECREF(r); else @@ -1773,7 +1778,7 @@ flush_io(void) } f = PySys_GetObject("stdout"); if (f != NULL) { - r = PyObject_CallMethod(f, "flush", ""); + r = _PyObject_CallMethodId(f, &PyId_flush, ""); if (r) Py_DECREF(r); else @@ -2205,6 +2210,7 @@ static void wait_for_thread_shutdown(void) { #ifdef WITH_THREAD + _Py_identifier(_shutdown); PyObject *result; PyThreadState *tstate = PyThreadState_GET(); PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, @@ -2214,7 +2220,7 @@ wait_for_thread_shutdown(void) PyErr_Clear(); return; } - result = PyObject_CallMethod(threading, "_shutdown", ""); + result = _PyObject_CallMethodId(threading, &PyId__shutdown, ""); if (result == NULL) { PyErr_WriteUnraisable(threading); } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 3576cedf63..f0aceada5f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -99,7 +99,8 @@ sys_displayhook_unencodable(PyObject *outf, PyObject *o) buffer = PyObject_GetAttrString(outf, "buffer"); if (buffer) { - result = PyObject_CallMethod(buffer, "write", "(O)", encoded); + _Py_identifier(write); + result = _PyObject_CallMethodId(buffer, &PyId_write, "(O)", encoded); Py_DECREF(buffer); Py_DECREF(encoded); if (result == NULL) diff --git a/Python/traceback.c b/Python/traceback.c index b66c96cda6..551f9d6228 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -152,6 +152,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * const char* filepath; Py_ssize_t len; PyObject* result; + _Py_identifier(open); filebytes = PyUnicode_EncodeFSDefault(filename); if (filebytes == NULL) { @@ -199,7 +200,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * namebuf[len++] = SEP; strcpy(namebuf+len, tail); - binary = PyObject_CallMethod(io, "open", "ss", namebuf, "rb"); + binary = _PyObject_CallMethodId(io, &PyId_open, "ss", namebuf, "rb"); if (binary != NULL) { result = binary; goto finally; @@ -231,6 +232,9 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) char buf[MAXPATHLEN+1]; int kind; void *data; + _Py_identifier(close); + _Py_identifier(open); + _Py_identifier(TextIOWrapper); /* open the file */ if (filename == NULL) @@ -239,7 +243,7 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) io = PyImport_ImportModuleNoBlock("io"); if (io == NULL) return -1; - binary = PyObject_CallMethod(io, "open", "Os", filename, "rb"); + binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb"); if (binary == NULL) { binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io); @@ -254,7 +258,7 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) 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); + fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding); Py_DECREF(io); Py_DECREF(binary); PyMem_FREE(found_encoding); @@ -273,7 +277,7 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) break; } } - res = PyObject_CallMethod(fob, "close", ""); + res = _PyObject_CallMethodId(fob, &PyId_close, ""); if (res) Py_DECREF(res); else -- cgit v1.2.1 From c3eb93fe1ce5f5ff2666fb9f34a6fd7c46279554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Mon, 10 Oct 2011 18:11:30 +0200 Subject: Use identifier API for PyObject_GetAttrString. --- Python/Python-ast.c | 601 ++++++++++++++++++++++++++++----------------------- Python/_warnings.c | 3 +- Python/bltinmodule.c | 14 +- Python/codecs.c | 6 +- Python/errors.c | 3 +- Python/import.c | 16 +- Python/pythonrun.c | 30 ++- Python/sysmodule.c | 9 +- 8 files changed, 385 insertions(+), 297 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index ff79757c35..2ed36cd220 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -7,6 +7,7 @@ static PyTypeObject AST_type; static PyTypeObject *mod_type; static PyObject* ast2obj_mod(void*); static PyTypeObject *Module_type; +_Py_identifier(body); static char *Module_fields[]={ "body", }; @@ -23,12 +24,18 @@ static char *Suite_fields[]={ "body", }; static PyTypeObject *stmt_type; +_Py_identifier(lineno); +_Py_identifier(col_offset); static char *stmt_attributes[] = { "lineno", "col_offset", }; static PyObject* ast2obj_stmt(void*); static PyTypeObject *FunctionDef_type; +_Py_identifier(name); +_Py_identifier(args); +_Py_identifier(decorator_list); +_Py_identifier(returns); static char *FunctionDef_fields[]={ "name", "args", @@ -37,6 +44,10 @@ static char *FunctionDef_fields[]={ "returns", }; static PyTypeObject *ClassDef_type; +_Py_identifier(bases); +_Py_identifier(keywords); +_Py_identifier(starargs); +_Py_identifier(kwargs); static char *ClassDef_fields[]={ "name", "bases", @@ -47,10 +58,12 @@ static char *ClassDef_fields[]={ "decorator_list", }; static PyTypeObject *Return_type; +_Py_identifier(value); static char *Return_fields[]={ "value", }; static PyTypeObject *Delete_type; +_Py_identifier(targets); static char *Delete_fields[]={ "targets", }; @@ -60,12 +73,16 @@ static char *Assign_fields[]={ "value", }; static PyTypeObject *AugAssign_type; +_Py_identifier(target); +_Py_identifier(op); static char *AugAssign_fields[]={ "target", "op", "value", }; static PyTypeObject *For_type; +_Py_identifier(iter); +_Py_identifier(orelse); static char *For_fields[]={ "target", "iter", @@ -73,6 +90,7 @@ static char *For_fields[]={ "orelse", }; static PyTypeObject *While_type; +_Py_identifier(test); static char *While_fields[]={ "test", "body", @@ -85,16 +103,21 @@ static char *If_fields[]={ "orelse", }; static PyTypeObject *With_type; +_Py_identifier(items); static char *With_fields[]={ "items", "body", }; static PyTypeObject *Raise_type; +_Py_identifier(exc); +_Py_identifier(cause); static char *Raise_fields[]={ "exc", "cause", }; static PyTypeObject *Try_type; +_Py_identifier(handlers); +_Py_identifier(finalbody); static char *Try_fields[]={ "body", "handlers", @@ -102,15 +125,19 @@ static char *Try_fields[]={ "finalbody", }; static PyTypeObject *Assert_type; +_Py_identifier(msg); static char *Assert_fields[]={ "test", "msg", }; static PyTypeObject *Import_type; +_Py_identifier(names); static char *Import_fields[]={ "names", }; static PyTypeObject *ImportFrom_type; +_Py_identifier(module); +_Py_identifier(level); static char *ImportFrom_fields[]={ "module", "names", @@ -138,17 +165,21 @@ static char *expr_attributes[] = { }; static PyObject* ast2obj_expr(void*); static PyTypeObject *BoolOp_type; +_Py_identifier(values); static char *BoolOp_fields[]={ "op", "values", }; static PyTypeObject *BinOp_type; +_Py_identifier(left); +_Py_identifier(right); static char *BinOp_fields[]={ "left", "op", "right", }; static PyTypeObject *UnaryOp_type; +_Py_identifier(operand); static char *UnaryOp_fields[]={ "op", "operand", @@ -165,15 +196,19 @@ static char *IfExp_fields[]={ "orelse", }; static PyTypeObject *Dict_type; +_Py_identifier(keys); static char *Dict_fields[]={ "keys", "values", }; static PyTypeObject *Set_type; +_Py_identifier(elts); static char *Set_fields[]={ "elts", }; static PyTypeObject *ListComp_type; +_Py_identifier(elt); +_Py_identifier(generators); static char *ListComp_fields[]={ "elt", "generators", @@ -184,6 +219,7 @@ static char *SetComp_fields[]={ "generators", }; static PyTypeObject *DictComp_type; +_Py_identifier(key); static char *DictComp_fields[]={ "key", "value", @@ -199,12 +235,15 @@ static char *Yield_fields[]={ "value", }; static PyTypeObject *Compare_type; +_Py_identifier(ops); +_Py_identifier(comparators); static char *Compare_fields[]={ "left", "ops", "comparators", }; static PyTypeObject *Call_type; +_Py_identifier(func); static char *Call_fields[]={ "func", "args", @@ -213,10 +252,12 @@ static char *Call_fields[]={ "kwargs", }; static PyTypeObject *Num_type; +_Py_identifier(n); static char *Num_fields[]={ "n", }; static PyTypeObject *Str_type; +_Py_identifier(s); static char *Str_fields[]={ "s", }; @@ -226,12 +267,15 @@ static char *Bytes_fields[]={ }; static PyTypeObject *Ellipsis_type; static PyTypeObject *Attribute_type; +_Py_identifier(attr); +_Py_identifier(ctx); static char *Attribute_fields[]={ "value", "attr", "ctx", }; static PyTypeObject *Subscript_type; +_Py_identifier(slice); static char *Subscript_fields[]={ "value", "slice", @@ -243,6 +287,7 @@ static char *Starred_fields[]={ "ctx", }; static PyTypeObject *Name_type; +_Py_identifier(id); static char *Name_fields[]={ "id", "ctx", @@ -270,12 +315,16 @@ static PyTypeObject *Param_type; static PyTypeObject *slice_type; static PyObject* ast2obj_slice(void*); static PyTypeObject *Slice_type; +_Py_identifier(lower); +_Py_identifier(upper); +_Py_identifier(step); static char *Slice_fields[]={ "lower", "upper", "step", }; static PyTypeObject *ExtSlice_type; +_Py_identifier(dims); static char *ExtSlice_fields[]={ "dims", }; @@ -331,6 +380,7 @@ static PyTypeObject *In_type; static PyTypeObject *NotIn_type; static PyTypeObject *comprehension_type; static PyObject* ast2obj_comprehension(void*); +_Py_identifier(ifs); static char *comprehension_fields[]={ "target", "iter", @@ -343,6 +393,7 @@ static char *excepthandler_attributes[] = { }; static PyObject* ast2obj_excepthandler(void*); static PyTypeObject *ExceptHandler_type; +_Py_identifier(type); static char *ExceptHandler_fields[]={ "type", "name", @@ -350,6 +401,13 @@ static char *ExceptHandler_fields[]={ }; static PyTypeObject *arguments_type; static PyObject* ast2obj_arguments(void*); +_Py_identifier(vararg); +_Py_identifier(varargannotation); +_Py_identifier(kwonlyargs); +_Py_identifier(kwarg); +_Py_identifier(kwargannotation); +_Py_identifier(defaults); +_Py_identifier(kw_defaults); static char *arguments_fields[]={ "args", "vararg", @@ -362,6 +420,8 @@ static char *arguments_fields[]={ }; static PyTypeObject *arg_type; static PyObject* ast2obj_arg(void*); +_Py_identifier(arg); +_Py_identifier(annotation); static char *arg_fields[]={ "arg", "annotation", @@ -374,12 +434,15 @@ static char *keyword_fields[]={ }; static PyTypeObject *alias_type; static PyObject* ast2obj_alias(void*); +_Py_identifier(asname); static char *alias_fields[]={ "name", "asname", }; static PyTypeObject *withitem_type; static PyObject* ast2obj_withitem(void*); +_Py_identifier(context_expr); +_Py_identifier(optional_vars); static char *withitem_fields[]={ "context_expr", "optional_vars", @@ -389,10 +452,11 @@ static char *withitem_fields[]={ static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { + _Py_identifier(_fields); Py_ssize_t i, numfields = 0; int res = -1; PyObject *key, *value, *fields; - fields = PyObject_GetAttrString((PyObject*)Py_TYPE(self), "_fields"); + fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields); if (!fields) PyErr_Clear(); if (fields) { @@ -442,7 +506,8 @@ static PyObject * ast_type_reduce(PyObject *self, PyObject *unused) { PyObject *res; - PyObject *dict = PyObject_GetAttrString(self, "__dict__"); + _Py_identifier(__dict__); + PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); if (dict == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); @@ -3415,11 +3480,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (isinstance) { asdl_seq* body; - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Module field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3451,11 +3516,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (isinstance) { asdl_seq* body; - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Interactive field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3487,9 +3552,9 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (isinstance) { expr_ty body; - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &body, arena); if (res != 0) goto failed; @@ -3510,11 +3575,11 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) if (isinstance) { asdl_seq* body; - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Suite field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3559,9 +3624,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) *out = NULL; return 0; } - if (PyObject_HasAttrString(obj, "lineno")) { + if (_PyObject_HasAttrId(obj, &PyId_lineno)) { int res; - tmp = PyObject_GetAttrString(obj, "lineno"); + tmp = _PyObject_GetAttrId(obj, &PyId_lineno); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &lineno, arena); if (res != 0) goto failed; @@ -3571,9 +3636,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from stmt"); return 1; } - if (PyObject_HasAttrString(obj, "col_offset")) { + if (_PyObject_HasAttrId(obj, &PyId_col_offset)) { int res; - tmp = PyObject_GetAttrString(obj, "col_offset"); + tmp = _PyObject_GetAttrId(obj, &PyId_col_offset); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &col_offset, arena); if (res != 0) goto failed; @@ -3594,9 +3659,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* decorator_list; expr_ty returns; - if (PyObject_HasAttrString(obj, "name")) { + if (_PyObject_HasAttrId(obj, &PyId_name)) { int res; - tmp = PyObject_GetAttrString(obj, "name"); + tmp = _PyObject_GetAttrId(obj, &PyId_name); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &name, arena); if (res != 0) goto failed; @@ -3606,9 +3671,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from FunctionDef"); return 1; } - if (PyObject_HasAttrString(obj, "args")) { + if (_PyObject_HasAttrId(obj, &PyId_args)) { int res; - tmp = PyObject_GetAttrString(obj, "args"); + tmp = _PyObject_GetAttrId(obj, &PyId_args); if (tmp == NULL) goto failed; res = obj2ast_arguments(tmp, &args, arena); if (res != 0) goto failed; @@ -3618,11 +3683,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from FunctionDef"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "FunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3643,11 +3708,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from FunctionDef"); return 1; } - if (PyObject_HasAttrString(obj, "decorator_list")) { + if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "decorator_list"); + tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "FunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3668,9 +3733,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from FunctionDef"); return 1; } - if (PyObject_HasAttrString(obj, "returns")) { + if (_PyObject_HasAttrId(obj, &PyId_returns)) { int res; - tmp = PyObject_GetAttrString(obj, "returns"); + tmp = _PyObject_GetAttrId(obj, &PyId_returns); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &returns, arena); if (res != 0) goto failed; @@ -3697,9 +3762,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* decorator_list; - if (PyObject_HasAttrString(obj, "name")) { + if (_PyObject_HasAttrId(obj, &PyId_name)) { int res; - tmp = PyObject_GetAttrString(obj, "name"); + tmp = _PyObject_GetAttrId(obj, &PyId_name); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &name, arena); if (res != 0) goto failed; @@ -3709,11 +3774,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from ClassDef"); return 1; } - if (PyObject_HasAttrString(obj, "bases")) { + if (_PyObject_HasAttrId(obj, &PyId_bases)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "bases"); + tmp = _PyObject_GetAttrId(obj, &PyId_bases); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ClassDef field \"bases\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3734,11 +3799,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"bases\" missing from ClassDef"); return 1; } - if (PyObject_HasAttrString(obj, "keywords")) { + if (_PyObject_HasAttrId(obj, &PyId_keywords)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "keywords"); + tmp = _PyObject_GetAttrId(obj, &PyId_keywords); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ClassDef field \"keywords\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3759,9 +3824,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from ClassDef"); return 1; } - if (PyObject_HasAttrString(obj, "starargs")) { + if (_PyObject_HasAttrId(obj, &PyId_starargs)) { int res; - tmp = PyObject_GetAttrString(obj, "starargs"); + tmp = _PyObject_GetAttrId(obj, &PyId_starargs); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &starargs, arena); if (res != 0) goto failed; @@ -3770,9 +3835,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } else { starargs = NULL; } - if (PyObject_HasAttrString(obj, "kwargs")) { + if (_PyObject_HasAttrId(obj, &PyId_kwargs)) { int res; - tmp = PyObject_GetAttrString(obj, "kwargs"); + tmp = _PyObject_GetAttrId(obj, &PyId_kwargs); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &kwargs, arena); if (res != 0) goto failed; @@ -3781,11 +3846,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } else { kwargs = NULL; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ClassDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3806,11 +3871,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from ClassDef"); return 1; } - if (PyObject_HasAttrString(obj, "decorator_list")) { + if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "decorator_list"); + tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ClassDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3843,9 +3908,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { expr_ty value; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -3865,11 +3930,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { asdl_seq* targets; - if (PyObject_HasAttrString(obj, "targets")) { + if (_PyObject_HasAttrId(obj, &PyId_targets)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "targets"); + tmp = _PyObject_GetAttrId(obj, &PyId_targets); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Delete field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3902,11 +3967,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* targets; expr_ty value; - if (PyObject_HasAttrString(obj, "targets")) { + if (_PyObject_HasAttrId(obj, &PyId_targets)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "targets"); + tmp = _PyObject_GetAttrId(obj, &PyId_targets); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Assign field \"targets\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -3927,9 +3992,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"targets\" missing from Assign"); return 1; } - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -3952,9 +4017,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) operator_ty op; expr_ty value; - if (PyObject_HasAttrString(obj, "target")) { + if (_PyObject_HasAttrId(obj, &PyId_target)) { int res; - tmp = PyObject_GetAttrString(obj, "target"); + tmp = _PyObject_GetAttrId(obj, &PyId_target); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &target, arena); if (res != 0) goto failed; @@ -3964,9 +4029,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AugAssign"); return 1; } - if (PyObject_HasAttrString(obj, "op")) { + if (_PyObject_HasAttrId(obj, &PyId_op)) { int res; - tmp = PyObject_GetAttrString(obj, "op"); + tmp = _PyObject_GetAttrId(obj, &PyId_op); if (tmp == NULL) goto failed; res = obj2ast_operator(tmp, &op, arena); if (res != 0) goto failed; @@ -3976,9 +4041,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from AugAssign"); return 1; } - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -4002,9 +4067,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* orelse; - if (PyObject_HasAttrString(obj, "target")) { + if (_PyObject_HasAttrId(obj, &PyId_target)) { int res; - tmp = PyObject_GetAttrString(obj, "target"); + tmp = _PyObject_GetAttrId(obj, &PyId_target); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &target, arena); if (res != 0) goto failed; @@ -4014,9 +4079,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from For"); return 1; } - if (PyObject_HasAttrString(obj, "iter")) { + if (_PyObject_HasAttrId(obj, &PyId_iter)) { int res; - tmp = PyObject_GetAttrString(obj, "iter"); + tmp = _PyObject_GetAttrId(obj, &PyId_iter); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &iter, arena); if (res != 0) goto failed; @@ -4026,11 +4091,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from For"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "For field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4051,11 +4116,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from For"); return 1; } - if (PyObject_HasAttrString(obj, "orelse")) { + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "orelse"); + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "For field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4090,9 +4155,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* orelse; - if (PyObject_HasAttrString(obj, "test")) { + if (_PyObject_HasAttrId(obj, &PyId_test)) { int res; - tmp = PyObject_GetAttrString(obj, "test"); + tmp = _PyObject_GetAttrId(obj, &PyId_test); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &test, arena); if (res != 0) goto failed; @@ -4102,11 +4167,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from While"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "While field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4127,11 +4192,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from While"); return 1; } - if (PyObject_HasAttrString(obj, "orelse")) { + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "orelse"); + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "While field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4165,9 +4230,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* orelse; - if (PyObject_HasAttrString(obj, "test")) { + if (_PyObject_HasAttrId(obj, &PyId_test)) { int res; - tmp = PyObject_GetAttrString(obj, "test"); + tmp = _PyObject_GetAttrId(obj, &PyId_test); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &test, arena); if (res != 0) goto failed; @@ -4177,11 +4242,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from If"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "If field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4202,11 +4267,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from If"); return 1; } - if (PyObject_HasAttrString(obj, "orelse")) { + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "orelse"); + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "If field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4239,11 +4304,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* items; asdl_seq* body; - if (PyObject_HasAttrString(obj, "items")) { + if (_PyObject_HasAttrId(obj, &PyId_items)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "items"); + tmp = _PyObject_GetAttrId(obj, &PyId_items); if (tmp == NULL) 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); @@ -4264,11 +4329,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from With"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "With field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4301,9 +4366,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) expr_ty exc; expr_ty cause; - if (PyObject_HasAttrString(obj, "exc")) { + if (_PyObject_HasAttrId(obj, &PyId_exc)) { int res; - tmp = PyObject_GetAttrString(obj, "exc"); + tmp = _PyObject_GetAttrId(obj, &PyId_exc); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &exc, arena); if (res != 0) goto failed; @@ -4312,9 +4377,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } else { exc = NULL; } - if (PyObject_HasAttrString(obj, "cause")) { + if (_PyObject_HasAttrId(obj, &PyId_cause)) { int res; - tmp = PyObject_GetAttrString(obj, "cause"); + tmp = _PyObject_GetAttrId(obj, &PyId_cause); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &cause, arena); if (res != 0) goto failed; @@ -4337,11 +4402,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* orelse; asdl_seq* finalbody; - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Try field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4362,11 +4427,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from Try"); return 1; } - if (PyObject_HasAttrString(obj, "handlers")) { + if (_PyObject_HasAttrId(obj, &PyId_handlers)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "handlers"); + tmp = _PyObject_GetAttrId(obj, &PyId_handlers); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Try field \"handlers\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4387,11 +4452,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"handlers\" missing from Try"); return 1; } - if (PyObject_HasAttrString(obj, "orelse")) { + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "orelse"); + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Try field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4412,11 +4477,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from Try"); return 1; } - if (PyObject_HasAttrString(obj, "finalbody")) { + if (_PyObject_HasAttrId(obj, &PyId_finalbody)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "finalbody"); + tmp = _PyObject_GetAttrId(obj, &PyId_finalbody); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Try field \"finalbody\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4450,9 +4515,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) expr_ty test; expr_ty msg; - if (PyObject_HasAttrString(obj, "test")) { + if (_PyObject_HasAttrId(obj, &PyId_test)) { int res; - tmp = PyObject_GetAttrString(obj, "test"); + tmp = _PyObject_GetAttrId(obj, &PyId_test); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &test, arena); if (res != 0) goto failed; @@ -4462,9 +4527,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from Assert"); return 1; } - if (PyObject_HasAttrString(obj, "msg")) { + if (_PyObject_HasAttrId(obj, &PyId_msg)) { int res; - tmp = PyObject_GetAttrString(obj, "msg"); + tmp = _PyObject_GetAttrId(obj, &PyId_msg); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &msg, arena); if (res != 0) goto failed; @@ -4484,11 +4549,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { asdl_seq* names; - if (PyObject_HasAttrString(obj, "names")) { + if (_PyObject_HasAttrId(obj, &PyId_names)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "names"); + tmp = _PyObject_GetAttrId(obj, &PyId_names); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Import field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4522,9 +4587,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* names; int level; - if (PyObject_HasAttrString(obj, "module")) { + if (_PyObject_HasAttrId(obj, &PyId_module)) { int res; - tmp = PyObject_GetAttrString(obj, "module"); + tmp = _PyObject_GetAttrId(obj, &PyId_module); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &module, arena); if (res != 0) goto failed; @@ -4533,11 +4598,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } else { module = NULL; } - if (PyObject_HasAttrString(obj, "names")) { + if (_PyObject_HasAttrId(obj, &PyId_names)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "names"); + tmp = _PyObject_GetAttrId(obj, &PyId_names); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ImportFrom field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4558,9 +4623,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"names\" missing from ImportFrom"); return 1; } - if (PyObject_HasAttrString(obj, "level")) { + if (_PyObject_HasAttrId(obj, &PyId_level)) { int res; - tmp = PyObject_GetAttrString(obj, "level"); + tmp = _PyObject_GetAttrId(obj, &PyId_level); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &level, arena); if (res != 0) goto failed; @@ -4581,11 +4646,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { asdl_seq* names; - if (PyObject_HasAttrString(obj, "names")) { + if (_PyObject_HasAttrId(obj, &PyId_names)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "names"); + tmp = _PyObject_GetAttrId(obj, &PyId_names); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Global field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4617,11 +4682,11 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { asdl_seq* names; - if (PyObject_HasAttrString(obj, "names")) { + if (_PyObject_HasAttrId(obj, &PyId_names)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "names"); + tmp = _PyObject_GetAttrId(obj, &PyId_names); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Nonlocal field \"names\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4653,9 +4718,9 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (isinstance) { expr_ty value; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -4719,9 +4784,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) *out = NULL; return 0; } - if (PyObject_HasAttrString(obj, "lineno")) { + if (_PyObject_HasAttrId(obj, &PyId_lineno)) { int res; - tmp = PyObject_GetAttrString(obj, "lineno"); + tmp = _PyObject_GetAttrId(obj, &PyId_lineno); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &lineno, arena); if (res != 0) goto failed; @@ -4731,9 +4796,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from expr"); return 1; } - if (PyObject_HasAttrString(obj, "col_offset")) { + if (_PyObject_HasAttrId(obj, &PyId_col_offset)) { int res; - tmp = PyObject_GetAttrString(obj, "col_offset"); + tmp = _PyObject_GetAttrId(obj, &PyId_col_offset); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &col_offset, arena); if (res != 0) goto failed; @@ -4751,9 +4816,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) boolop_ty op; asdl_seq* values; - if (PyObject_HasAttrString(obj, "op")) { + if (_PyObject_HasAttrId(obj, &PyId_op)) { int res; - tmp = PyObject_GetAttrString(obj, "op"); + tmp = _PyObject_GetAttrId(obj, &PyId_op); if (tmp == NULL) goto failed; res = obj2ast_boolop(tmp, &op, arena); if (res != 0) goto failed; @@ -4763,11 +4828,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BoolOp"); return 1; } - if (PyObject_HasAttrString(obj, "values")) { + if (_PyObject_HasAttrId(obj, &PyId_values)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "values"); + tmp = _PyObject_GetAttrId(obj, &PyId_values); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "BoolOp field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4801,9 +4866,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) operator_ty op; expr_ty right; - if (PyObject_HasAttrString(obj, "left")) { + if (_PyObject_HasAttrId(obj, &PyId_left)) { int res; - tmp = PyObject_GetAttrString(obj, "left"); + tmp = _PyObject_GetAttrId(obj, &PyId_left); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &left, arena); if (res != 0) goto failed; @@ -4813,9 +4878,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from BinOp"); return 1; } - if (PyObject_HasAttrString(obj, "op")) { + if (_PyObject_HasAttrId(obj, &PyId_op)) { int res; - tmp = PyObject_GetAttrString(obj, "op"); + tmp = _PyObject_GetAttrId(obj, &PyId_op); if (tmp == NULL) goto failed; res = obj2ast_operator(tmp, &op, arena); if (res != 0) goto failed; @@ -4825,9 +4890,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from BinOp"); return 1; } - if (PyObject_HasAttrString(obj, "right")) { + if (_PyObject_HasAttrId(obj, &PyId_right)) { int res; - tmp = PyObject_GetAttrString(obj, "right"); + tmp = _PyObject_GetAttrId(obj, &PyId_right); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &right, arena); if (res != 0) goto failed; @@ -4849,9 +4914,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) unaryop_ty op; expr_ty operand; - if (PyObject_HasAttrString(obj, "op")) { + if (_PyObject_HasAttrId(obj, &PyId_op)) { int res; - tmp = PyObject_GetAttrString(obj, "op"); + tmp = _PyObject_GetAttrId(obj, &PyId_op); if (tmp == NULL) goto failed; res = obj2ast_unaryop(tmp, &op, arena); if (res != 0) goto failed; @@ -4861,9 +4926,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"op\" missing from UnaryOp"); return 1; } - if (PyObject_HasAttrString(obj, "operand")) { + if (_PyObject_HasAttrId(obj, &PyId_operand)) { int res; - tmp = PyObject_GetAttrString(obj, "operand"); + tmp = _PyObject_GetAttrId(obj, &PyId_operand); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &operand, arena); if (res != 0) goto failed; @@ -4885,9 +4950,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) arguments_ty args; expr_ty body; - if (PyObject_HasAttrString(obj, "args")) { + if (_PyObject_HasAttrId(obj, &PyId_args)) { int res; - tmp = PyObject_GetAttrString(obj, "args"); + tmp = _PyObject_GetAttrId(obj, &PyId_args); if (tmp == NULL) goto failed; res = obj2ast_arguments(tmp, &args, arena); if (res != 0) goto failed; @@ -4897,9 +4962,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Lambda"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &body, arena); if (res != 0) goto failed; @@ -4922,9 +4987,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty body; expr_ty orelse; - if (PyObject_HasAttrString(obj, "test")) { + if (_PyObject_HasAttrId(obj, &PyId_test)) { int res; - tmp = PyObject_GetAttrString(obj, "test"); + tmp = _PyObject_GetAttrId(obj, &PyId_test); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &test, arena); if (res != 0) goto failed; @@ -4934,9 +4999,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"test\" missing from IfExp"); return 1; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &body, arena); if (res != 0) goto failed; @@ -4946,9 +5011,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from IfExp"); return 1; } - if (PyObject_HasAttrString(obj, "orelse")) { + if (_PyObject_HasAttrId(obj, &PyId_orelse)) { int res; - tmp = PyObject_GetAttrString(obj, "orelse"); + tmp = _PyObject_GetAttrId(obj, &PyId_orelse); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &orelse, arena); if (res != 0) goto failed; @@ -4970,11 +5035,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) asdl_seq* keys; asdl_seq* values; - if (PyObject_HasAttrString(obj, "keys")) { + if (_PyObject_HasAttrId(obj, &PyId_keys)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "keys"); + tmp = _PyObject_GetAttrId(obj, &PyId_keys); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Dict field \"keys\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -4995,11 +5060,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"keys\" missing from Dict"); return 1; } - if (PyObject_HasAttrString(obj, "values")) { + if (_PyObject_HasAttrId(obj, &PyId_values)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "values"); + tmp = _PyObject_GetAttrId(obj, &PyId_values); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Dict field \"values\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5031,11 +5096,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (isinstance) { asdl_seq* elts; - if (PyObject_HasAttrString(obj, "elts")) { + if (_PyObject_HasAttrId(obj, &PyId_elts)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "elts"); + tmp = _PyObject_GetAttrId(obj, &PyId_elts); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Set field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5068,9 +5133,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty elt; asdl_seq* generators; - if (PyObject_HasAttrString(obj, "elt")) { + if (_PyObject_HasAttrId(obj, &PyId_elt)) { int res; - tmp = PyObject_GetAttrString(obj, "elt"); + tmp = _PyObject_GetAttrId(obj, &PyId_elt); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &elt, arena); if (res != 0) goto failed; @@ -5080,11 +5145,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from ListComp"); return 1; } - if (PyObject_HasAttrString(obj, "generators")) { + if (_PyObject_HasAttrId(obj, &PyId_generators)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "generators"); + tmp = _PyObject_GetAttrId(obj, &PyId_generators); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ListComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5117,9 +5182,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty elt; asdl_seq* generators; - if (PyObject_HasAttrString(obj, "elt")) { + if (_PyObject_HasAttrId(obj, &PyId_elt)) { int res; - tmp = PyObject_GetAttrString(obj, "elt"); + tmp = _PyObject_GetAttrId(obj, &PyId_elt); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &elt, arena); if (res != 0) goto failed; @@ -5129,11 +5194,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from SetComp"); return 1; } - if (PyObject_HasAttrString(obj, "generators")) { + if (_PyObject_HasAttrId(obj, &PyId_generators)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "generators"); + tmp = _PyObject_GetAttrId(obj, &PyId_generators); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "SetComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5167,9 +5232,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty value; asdl_seq* generators; - if (PyObject_HasAttrString(obj, "key")) { + if (_PyObject_HasAttrId(obj, &PyId_key)) { int res; - tmp = PyObject_GetAttrString(obj, "key"); + tmp = _PyObject_GetAttrId(obj, &PyId_key); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &key, arena); if (res != 0) goto failed; @@ -5179,9 +5244,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"key\" missing from DictComp"); return 1; } - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -5191,11 +5256,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from DictComp"); return 1; } - if (PyObject_HasAttrString(obj, "generators")) { + if (_PyObject_HasAttrId(obj, &PyId_generators)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "generators"); + tmp = _PyObject_GetAttrId(obj, &PyId_generators); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "DictComp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5229,9 +5294,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty elt; asdl_seq* generators; - if (PyObject_HasAttrString(obj, "elt")) { + if (_PyObject_HasAttrId(obj, &PyId_elt)) { int res; - tmp = PyObject_GetAttrString(obj, "elt"); + tmp = _PyObject_GetAttrId(obj, &PyId_elt); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &elt, arena); if (res != 0) goto failed; @@ -5241,11 +5306,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"elt\" missing from GeneratorExp"); return 1; } - if (PyObject_HasAttrString(obj, "generators")) { + if (_PyObject_HasAttrId(obj, &PyId_generators)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "generators"); + tmp = _PyObject_GetAttrId(obj, &PyId_generators); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "GeneratorExp field \"generators\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5277,9 +5342,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (isinstance) { expr_ty value; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -5301,9 +5366,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) asdl_int_seq* ops; asdl_seq* comparators; - if (PyObject_HasAttrString(obj, "left")) { + if (_PyObject_HasAttrId(obj, &PyId_left)) { int res; - tmp = PyObject_GetAttrString(obj, "left"); + tmp = _PyObject_GetAttrId(obj, &PyId_left); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &left, arena); if (res != 0) goto failed; @@ -5313,11 +5378,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"left\" missing from Compare"); return 1; } - if (PyObject_HasAttrString(obj, "ops")) { + if (_PyObject_HasAttrId(obj, &PyId_ops)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "ops"); + tmp = _PyObject_GetAttrId(obj, &PyId_ops); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Compare field \"ops\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5338,11 +5403,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"ops\" missing from Compare"); return 1; } - if (PyObject_HasAttrString(obj, "comparators")) { + if (_PyObject_HasAttrId(obj, &PyId_comparators)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "comparators"); + tmp = _PyObject_GetAttrId(obj, &PyId_comparators); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Compare field \"comparators\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5379,9 +5444,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty starargs; expr_ty kwargs; - if (PyObject_HasAttrString(obj, "func")) { + if (_PyObject_HasAttrId(obj, &PyId_func)) { int res; - tmp = PyObject_GetAttrString(obj, "func"); + tmp = _PyObject_GetAttrId(obj, &PyId_func); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &func, arena); if (res != 0) goto failed; @@ -5391,11 +5456,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"func\" missing from Call"); return 1; } - if (PyObject_HasAttrString(obj, "args")) { + if (_PyObject_HasAttrId(obj, &PyId_args)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "args"); + tmp = _PyObject_GetAttrId(obj, &PyId_args); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Call field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5416,11 +5481,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from Call"); return 1; } - if (PyObject_HasAttrString(obj, "keywords")) { + if (_PyObject_HasAttrId(obj, &PyId_keywords)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "keywords"); + tmp = _PyObject_GetAttrId(obj, &PyId_keywords); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Call field \"keywords\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5441,9 +5506,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"keywords\" missing from Call"); return 1; } - if (PyObject_HasAttrString(obj, "starargs")) { + if (_PyObject_HasAttrId(obj, &PyId_starargs)) { int res; - tmp = PyObject_GetAttrString(obj, "starargs"); + tmp = _PyObject_GetAttrId(obj, &PyId_starargs); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &starargs, arena); if (res != 0) goto failed; @@ -5452,9 +5517,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) } else { starargs = NULL; } - if (PyObject_HasAttrString(obj, "kwargs")) { + if (_PyObject_HasAttrId(obj, &PyId_kwargs)) { int res; - tmp = PyObject_GetAttrString(obj, "kwargs"); + tmp = _PyObject_GetAttrId(obj, &PyId_kwargs); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &kwargs, arena); if (res != 0) goto failed; @@ -5475,9 +5540,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (isinstance) { object n; - if (PyObject_HasAttrString(obj, "n")) { + if (_PyObject_HasAttrId(obj, &PyId_n)) { int res; - tmp = PyObject_GetAttrString(obj, "n"); + tmp = _PyObject_GetAttrId(obj, &PyId_n); if (tmp == NULL) goto failed; res = obj2ast_object(tmp, &n, arena); if (res != 0) goto failed; @@ -5498,9 +5563,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (isinstance) { string s; - if (PyObject_HasAttrString(obj, "s")) { + if (_PyObject_HasAttrId(obj, &PyId_s)) { int res; - tmp = PyObject_GetAttrString(obj, "s"); + tmp = _PyObject_GetAttrId(obj, &PyId_s); if (tmp == NULL) goto failed; res = obj2ast_string(tmp, &s, arena); if (res != 0) goto failed; @@ -5521,9 +5586,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) if (isinstance) { bytes s; - if (PyObject_HasAttrString(obj, "s")) { + if (_PyObject_HasAttrId(obj, &PyId_s)) { int res; - tmp = PyObject_GetAttrString(obj, "s"); + tmp = _PyObject_GetAttrId(obj, &PyId_s); if (tmp == NULL) goto failed; res = obj2ast_bytes(tmp, &s, arena); if (res != 0) goto failed; @@ -5556,9 +5621,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) identifier attr; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -5568,9 +5633,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Attribute"); return 1; } - if (PyObject_HasAttrString(obj, "attr")) { + if (_PyObject_HasAttrId(obj, &PyId_attr)) { int res; - tmp = PyObject_GetAttrString(obj, "attr"); + tmp = _PyObject_GetAttrId(obj, &PyId_attr); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &attr, arena); if (res != 0) goto failed; @@ -5580,9 +5645,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"attr\" missing from Attribute"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5605,9 +5670,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) slice_ty slice; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -5617,9 +5682,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Subscript"); return 1; } - if (PyObject_HasAttrString(obj, "slice")) { + if (_PyObject_HasAttrId(obj, &PyId_slice)) { int res; - tmp = PyObject_GetAttrString(obj, "slice"); + tmp = _PyObject_GetAttrId(obj, &PyId_slice); if (tmp == NULL) goto failed; res = obj2ast_slice(tmp, &slice, arena); if (res != 0) goto failed; @@ -5629,9 +5694,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"slice\" missing from Subscript"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5653,9 +5718,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) expr_ty value; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -5665,9 +5730,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Starred"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5689,9 +5754,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) identifier id; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "id")) { + if (_PyObject_HasAttrId(obj, &PyId_id)) { int res; - tmp = PyObject_GetAttrString(obj, "id"); + tmp = _PyObject_GetAttrId(obj, &PyId_id); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &id, arena); if (res != 0) goto failed; @@ -5701,9 +5766,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"id\" missing from Name"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5725,11 +5790,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) asdl_seq* elts; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "elts")) { + if (_PyObject_HasAttrId(obj, &PyId_elts)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "elts"); + tmp = _PyObject_GetAttrId(obj, &PyId_elts); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "List field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5750,9 +5815,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from List"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5774,11 +5839,11 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) asdl_seq* elts; expr_context_ty ctx; - if (PyObject_HasAttrString(obj, "elts")) { + if (_PyObject_HasAttrId(obj, &PyId_elts)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "elts"); + tmp = _PyObject_GetAttrId(obj, &PyId_elts); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "Tuple field \"elts\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5799,9 +5864,9 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"elts\" missing from Tuple"); return 1; } - if (PyObject_HasAttrString(obj, "ctx")) { + if (_PyObject_HasAttrId(obj, &PyId_ctx)) { int res; - tmp = PyObject_GetAttrString(obj, "ctx"); + tmp = _PyObject_GetAttrId(obj, &PyId_ctx); if (tmp == NULL) goto failed; res = obj2ast_expr_context(tmp, &ctx, arena); if (res != 0) goto failed; @@ -5900,9 +5965,9 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) expr_ty upper; expr_ty step; - if (PyObject_HasAttrString(obj, "lower")) { + if (_PyObject_HasAttrId(obj, &PyId_lower)) { int res; - tmp = PyObject_GetAttrString(obj, "lower"); + tmp = _PyObject_GetAttrId(obj, &PyId_lower); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &lower, arena); if (res != 0) goto failed; @@ -5911,9 +5976,9 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) } else { lower = NULL; } - if (PyObject_HasAttrString(obj, "upper")) { + if (_PyObject_HasAttrId(obj, &PyId_upper)) { int res; - tmp = PyObject_GetAttrString(obj, "upper"); + tmp = _PyObject_GetAttrId(obj, &PyId_upper); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &upper, arena); if (res != 0) goto failed; @@ -5922,9 +5987,9 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) } else { upper = NULL; } - if (PyObject_HasAttrString(obj, "step")) { + if (_PyObject_HasAttrId(obj, &PyId_step)) { int res; - tmp = PyObject_GetAttrString(obj, "step"); + tmp = _PyObject_GetAttrId(obj, &PyId_step); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &step, arena); if (res != 0) goto failed; @@ -5944,11 +6009,11 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) if (isinstance) { asdl_seq* dims; - if (PyObject_HasAttrString(obj, "dims")) { + if (_PyObject_HasAttrId(obj, &PyId_dims)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "dims"); + tmp = _PyObject_GetAttrId(obj, &PyId_dims); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ExtSlice field \"dims\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -5980,9 +6045,9 @@ obj2ast_slice(PyObject* obj, slice_ty* out, PyArena* arena) if (isinstance) { expr_ty value; - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -6275,9 +6340,9 @@ obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena) expr_ty iter; asdl_seq* ifs; - if (PyObject_HasAttrString(obj, "target")) { + if (_PyObject_HasAttrId(obj, &PyId_target)) { int res; - tmp = PyObject_GetAttrString(obj, "target"); + tmp = _PyObject_GetAttrId(obj, &PyId_target); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &target, arena); if (res != 0) goto failed; @@ -6287,9 +6352,9 @@ obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from comprehension"); return 1; } - if (PyObject_HasAttrString(obj, "iter")) { + if (_PyObject_HasAttrId(obj, &PyId_iter)) { int res; - tmp = PyObject_GetAttrString(obj, "iter"); + tmp = _PyObject_GetAttrId(obj, &PyId_iter); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &iter, arena); if (res != 0) goto failed; @@ -6299,11 +6364,11 @@ obj2ast_comprehension(PyObject* obj, comprehension_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from comprehension"); return 1; } - if (PyObject_HasAttrString(obj, "ifs")) { + if (_PyObject_HasAttrId(obj, &PyId_ifs)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "ifs"); + tmp = _PyObject_GetAttrId(obj, &PyId_ifs); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "comprehension field \"ifs\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6344,9 +6409,9 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) *out = NULL; return 0; } - if (PyObject_HasAttrString(obj, "lineno")) { + if (_PyObject_HasAttrId(obj, &PyId_lineno)) { int res; - tmp = PyObject_GetAttrString(obj, "lineno"); + tmp = _PyObject_GetAttrId(obj, &PyId_lineno); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &lineno, arena); if (res != 0) goto failed; @@ -6356,9 +6421,9 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"lineno\" missing from excepthandler"); return 1; } - if (PyObject_HasAttrString(obj, "col_offset")) { + if (_PyObject_HasAttrId(obj, &PyId_col_offset)) { int res; - tmp = PyObject_GetAttrString(obj, "col_offset"); + tmp = _PyObject_GetAttrId(obj, &PyId_col_offset); if (tmp == NULL) goto failed; res = obj2ast_int(tmp, &col_offset, arena); if (res != 0) goto failed; @@ -6377,9 +6442,9 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) identifier name; asdl_seq* body; - if (PyObject_HasAttrString(obj, "type")) { + if (_PyObject_HasAttrId(obj, &PyId_type)) { int res; - tmp = PyObject_GetAttrString(obj, "type"); + tmp = _PyObject_GetAttrId(obj, &PyId_type); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &type, arena); if (res != 0) goto failed; @@ -6388,9 +6453,9 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) } else { type = NULL; } - if (PyObject_HasAttrString(obj, "name")) { + if (_PyObject_HasAttrId(obj, &PyId_name)) { int res; - tmp = PyObject_GetAttrString(obj, "name"); + tmp = _PyObject_GetAttrId(obj, &PyId_name); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &name, arena); if (res != 0) goto failed; @@ -6399,11 +6464,11 @@ obj2ast_excepthandler(PyObject* obj, excepthandler_ty* out, PyArena* arena) } else { name = NULL; } - if (PyObject_HasAttrString(obj, "body")) { + if (_PyObject_HasAttrId(obj, &PyId_body)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "body"); + tmp = _PyObject_GetAttrId(obj, &PyId_body); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "ExceptHandler field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6449,11 +6514,11 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) asdl_seq* defaults; asdl_seq* kw_defaults; - if (PyObject_HasAttrString(obj, "args")) { + if (_PyObject_HasAttrId(obj, &PyId_args)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "args"); + tmp = _PyObject_GetAttrId(obj, &PyId_args); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "arguments field \"args\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6474,9 +6539,9 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from arguments"); return 1; } - if (PyObject_HasAttrString(obj, "vararg")) { + if (_PyObject_HasAttrId(obj, &PyId_vararg)) { int res; - tmp = PyObject_GetAttrString(obj, "vararg"); + tmp = _PyObject_GetAttrId(obj, &PyId_vararg); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &vararg, arena); if (res != 0) goto failed; @@ -6485,9 +6550,9 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } else { vararg = NULL; } - if (PyObject_HasAttrString(obj, "varargannotation")) { + if (_PyObject_HasAttrId(obj, &PyId_varargannotation)) { int res; - tmp = PyObject_GetAttrString(obj, "varargannotation"); + tmp = _PyObject_GetAttrId(obj, &PyId_varargannotation); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &varargannotation, arena); if (res != 0) goto failed; @@ -6496,11 +6561,11 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } else { varargannotation = NULL; } - if (PyObject_HasAttrString(obj, "kwonlyargs")) { + if (_PyObject_HasAttrId(obj, &PyId_kwonlyargs)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "kwonlyargs"); + tmp = _PyObject_GetAttrId(obj, &PyId_kwonlyargs); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "arguments field \"kwonlyargs\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6521,9 +6586,9 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"kwonlyargs\" missing from arguments"); return 1; } - if (PyObject_HasAttrString(obj, "kwarg")) { + if (_PyObject_HasAttrId(obj, &PyId_kwarg)) { int res; - tmp = PyObject_GetAttrString(obj, "kwarg"); + tmp = _PyObject_GetAttrId(obj, &PyId_kwarg); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &kwarg, arena); if (res != 0) goto failed; @@ -6532,9 +6597,9 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } else { kwarg = NULL; } - if (PyObject_HasAttrString(obj, "kwargannotation")) { + if (_PyObject_HasAttrId(obj, &PyId_kwargannotation)) { int res; - tmp = PyObject_GetAttrString(obj, "kwargannotation"); + tmp = _PyObject_GetAttrId(obj, &PyId_kwargannotation); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &kwargannotation, arena); if (res != 0) goto failed; @@ -6543,11 +6608,11 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) } else { kwargannotation = NULL; } - if (PyObject_HasAttrString(obj, "defaults")) { + if (_PyObject_HasAttrId(obj, &PyId_defaults)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "defaults"); + tmp = _PyObject_GetAttrId(obj, &PyId_defaults); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "arguments field \"defaults\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6568,11 +6633,11 @@ obj2ast_arguments(PyObject* obj, arguments_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"defaults\" missing from arguments"); return 1; } - if (PyObject_HasAttrString(obj, "kw_defaults")) { + if (_PyObject_HasAttrId(obj, &PyId_kw_defaults)) { int res; Py_ssize_t len; Py_ssize_t i; - tmp = PyObject_GetAttrString(obj, "kw_defaults"); + tmp = _PyObject_GetAttrId(obj, &PyId_kw_defaults); if (tmp == NULL) goto failed; if (!PyList_Check(tmp)) { PyErr_Format(PyExc_TypeError, "arguments field \"kw_defaults\" must be a list, not a %.200s", tmp->ob_type->tp_name); @@ -6608,9 +6673,9 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena) identifier arg; expr_ty annotation; - if (PyObject_HasAttrString(obj, "arg")) { + if (_PyObject_HasAttrId(obj, &PyId_arg)) { int res; - tmp = PyObject_GetAttrString(obj, "arg"); + tmp = _PyObject_GetAttrId(obj, &PyId_arg); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &arg, arena); if (res != 0) goto failed; @@ -6620,9 +6685,9 @@ obj2ast_arg(PyObject* obj, arg_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from arg"); return 1; } - if (PyObject_HasAttrString(obj, "annotation")) { + if (_PyObject_HasAttrId(obj, &PyId_annotation)) { int res; - tmp = PyObject_GetAttrString(obj, "annotation"); + tmp = _PyObject_GetAttrId(obj, &PyId_annotation); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &annotation, arena); if (res != 0) goto failed; @@ -6645,9 +6710,9 @@ obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena) identifier arg; expr_ty value; - if (PyObject_HasAttrString(obj, "arg")) { + if (_PyObject_HasAttrId(obj, &PyId_arg)) { int res; - tmp = PyObject_GetAttrString(obj, "arg"); + tmp = _PyObject_GetAttrId(obj, &PyId_arg); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &arg, arena); if (res != 0) goto failed; @@ -6657,9 +6722,9 @@ obj2ast_keyword(PyObject* obj, keyword_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"arg\" missing from keyword"); return 1; } - if (PyObject_HasAttrString(obj, "value")) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = PyObject_GetAttrString(obj, "value"); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; @@ -6683,9 +6748,9 @@ obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena) identifier name; identifier asname; - if (PyObject_HasAttrString(obj, "name")) { + if (_PyObject_HasAttrId(obj, &PyId_name)) { int res; - tmp = PyObject_GetAttrString(obj, "name"); + tmp = _PyObject_GetAttrId(obj, &PyId_name); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &name, arena); if (res != 0) goto failed; @@ -6695,9 +6760,9 @@ obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from alias"); return 1; } - if (PyObject_HasAttrString(obj, "asname")) { + if (_PyObject_HasAttrId(obj, &PyId_asname)) { int res; - tmp = PyObject_GetAttrString(obj, "asname"); + tmp = _PyObject_GetAttrId(obj, &PyId_asname); if (tmp == NULL) goto failed; res = obj2ast_identifier(tmp, &asname, arena); if (res != 0) goto failed; @@ -6720,9 +6785,9 @@ obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena) expr_ty context_expr; expr_ty optional_vars; - if (PyObject_HasAttrString(obj, "context_expr")) { + if (_PyObject_HasAttrId(obj, &PyId_context_expr)) { int res; - tmp = PyObject_GetAttrString(obj, "context_expr"); + tmp = _PyObject_GetAttrId(obj, &PyId_context_expr); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &context_expr, arena); if (res != 0) goto failed; @@ -6732,9 +6797,9 @@ obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena) PyErr_SetString(PyExc_TypeError, "required field \"context_expr\" missing from withitem"); return 1; } - if (PyObject_HasAttrString(obj, "optional_vars")) { + if (_PyObject_HasAttrId(obj, &PyId_optional_vars)) { int res; - tmp = PyObject_GetAttrString(obj, "optional_vars"); + tmp = _PyObject_GetAttrId(obj, &PyId_optional_vars); if (tmp == NULL) goto failed; res = obj2ast_expr(tmp, &optional_vars, arena); if (res != 0) goto failed; diff --git a/Python/_warnings.c b/Python/_warnings.c index e5631079a9..ebc9cb808c 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -247,10 +247,11 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject PyObject *f_stderr; PyObject *name; char lineno_str[128]; + _Py_identifier(__name__); PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); - name = PyObject_GetAttrString(category, "__name__"); + name = _PyObject_GetAttrId(category, &PyId___name__); if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */ return; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c174e9d5ef..9849df6f67 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -41,6 +41,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; + _Py_identifier(__prepare__); assert(args != NULL); if (!PyTuple_Check(args)) { @@ -95,7 +96,7 @@ builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) } Py_INCREF(meta); } - prep = PyObject_GetAttrString(meta, "__prepare__"); + prep = _PyObject_GetAttrId(meta, &PyId___prepare__); if (prep == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); @@ -1613,8 +1614,9 @@ builtin_input(PyObject *self, PyObject *args) char *stdin_encoding_str; PyObject *result; size_t len; + _Py_identifier(encoding); - stdin_encoding = PyObject_GetAttrString(fin, "encoding"); + stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding); if (!stdin_encoding) /* stdin is a text stream, so it must have an encoding. */ @@ -1633,7 +1635,7 @@ builtin_input(PyObject *self, PyObject *args) PyObject *stringpo; PyObject *stdout_encoding; char *stdout_encoding_str; - stdout_encoding = PyObject_GetAttrString(fout, "encoding"); + stdout_encoding = _PyObject_GetAttrId(fout, &PyId_encoding); if (stdout_encoding == NULL) { Py_DECREF(stdin_encoding); return NULL; @@ -1788,6 +1790,7 @@ builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) PyObject *callable; static char *kwlist[] = {"iterable", "key", "reverse", 0}; int reverse; + _Py_identifier(sort); /* args 1-3 should match listsort in Objects/listobject.c */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", @@ -1798,7 +1801,7 @@ builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) if (newlist == NULL) return NULL; - callable = PyObject_GetAttrString(newlist, "sort"); + callable = _PyObject_GetAttrId(newlist, &PyId_sort); if (callable == NULL) { Py_DECREF(newlist); return NULL; @@ -1844,7 +1847,8 @@ builtin_vars(PyObject *self, PyObject *args) Py_INCREF(d); } else { - d = PyObject_GetAttrString(v, "__dict__"); + _Py_identifier(__dict__); + d = _PyObject_GetAttrId(v, &PyId___dict__); if (d == NULL) { PyErr_SetString(PyExc_TypeError, "vars() argument must have __dict__ attribute"); diff --git a/Python/codecs.c b/Python/codecs.c index 0008bdcbdc..79dfe89aba 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -465,9 +465,11 @@ PyObject *PyCodec_LookupError(const char *name) static void wrong_exception_type(PyObject *exc) { - PyObject *type = PyObject_GetAttrString(exc, "__class__"); + _Py_identifier(__class__); + _Py_identifier(__name__); + PyObject *type = _PyObject_GetAttrId(exc, &PyId___class__); if (type != NULL) { - PyObject *name = PyObject_GetAttrString(type, "__name__"); + PyObject *name = _PyObject_GetAttrId(type, &PyId___name__); Py_DECREF(type); if (name != NULL) { PyErr_Format(PyExc_TypeError, diff --git a/Python/errors.c b/Python/errors.c index 149151ebfa..02f84b46ac 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -707,6 +707,7 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc, void PyErr_WriteUnraisable(PyObject *obj) { + _Py_identifier(__module__); PyObject *f, *t, *v, *tb; PyErr_Fetch(&t, &v, &tb); f = PySys_GetObject("stderr"); @@ -723,7 +724,7 @@ PyErr_WriteUnraisable(PyObject *obj) className = dot+1; } - moduleName = PyObject_GetAttrString(t, "__module__"); + moduleName = _PyObject_GetAttrId(t, &PyId___module__); if (moduleName == NULL) PyFile_WriteString("", f); else { diff --git a/Python/import.c b/Python/import.c index 6eca90a0f7..3d6c6ed1d4 100644 --- a/Python/import.c +++ b/Python/import.c @@ -154,7 +154,7 @@ static const struct filedescr _PyImport_StandardFiletab[] = { }; static PyObject *initstr = NULL; - +_Py_identifier(__path__); /* Initialize things */ @@ -248,8 +248,9 @@ _PyImportHooks_Init(void) PySys_WriteStderr("# can't import zipimport\n"); } else { - PyObject *zipimporter = PyObject_GetAttrString(zimpimport, - "zipimporter"); + _Py_identifier(zipimporter); + PyObject *zipimporter = _PyObject_GetAttrId(zimpimport, + &PyId_zipimporter); Py_DECREF(zimpimport); if (zipimporter == NULL) { PyErr_Clear(); /* No zipimporter object -- okay */ @@ -3203,7 +3204,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, PyObject *fullname; Py_ssize_t fromlist_len; - if (!PyObject_HasAttrString(mod, "__path__")) + if (!_PyObject_HasAttrId(mod, &PyId___path__)) return 1; fromlist_len = PySequence_Size(fromlist); @@ -3221,11 +3222,12 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, } if (PyUnicode_READ_CHAR(item, 0) == '*') { PyObject *all; + _Py_identifier(__all__); Py_DECREF(item); /* See if the package defines __all__ */ if (recursive) continue; /* Avoid endless recursion */ - all = PyObject_GetAttrString(mod, "__all__"); + all = _PyObject_GetAttrId(mod, &PyId___all__); if (all == NULL) PyErr_Clear(); else { @@ -3313,7 +3315,7 @@ import_submodule(PyObject *mod, PyObject *subname, PyObject *fullname) if (mod == Py_None) path_list = NULL; else { - path_list = PyObject_GetAttrString(mod, "__path__"); + path_list = _PyObject_GetAttrId(mod, &PyId___path__); if (path_list == NULL) { PyErr_Clear(); Py_INCREF(Py_None); @@ -3424,7 +3426,7 @@ PyImport_ReloadModule(PyObject *m) goto error; } Py_DECREF(parentname); - path_list = PyObject_GetAttrString(parent, "__path__"); + path_list = _PyObject_GetAttrId(parent, &PyId___path__); if (path_list == NULL) PyErr_Clear(); subname++; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 0ef36bbb8c..df0d1b34e1 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -141,12 +141,13 @@ get_codec_name(const char *encoding) { char *name_utf8, *name_str; PyObject *codec, *name = NULL; + _Py_identifier(name); codec = _PyCodec_Lookup(encoding); if (!codec) goto error; - name = PyObject_GetAttrString(codec, "name"); + name = _PyObject_GetAttrId(codec, &PyId_name); Py_CLEAR(codec); if (!name) goto error; @@ -830,7 +831,8 @@ create_stdio(PyObject* io, goto error; if (buffering) { - raw = PyObject_GetAttrString(buf, "raw"); + _Py_identifier(raw); + raw = _PyObject_GetAttrId(buf, &PyId_raw); if (raw == NULL) goto error; } @@ -1115,13 +1117,14 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags PyArena *arena; char *ps1 = "", *ps2 = "", *enc = NULL; int errcode = 0; + _Py_identifier(encoding); if (fp == stdin) { /* Fetch encoding from sys.stdin */ v = PySys_GetObject("stdin"); if (v == NULL || v == Py_None) return -1; - oenc = PyObject_GetAttrString(v, "encoding"); + oenc = _PyObject_GetAttrId(v, &PyId_encoding); if (!oenc) return -1; enc = _PyUnicode_AsString(oenc); @@ -1318,6 +1321,11 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, { long hold; PyObject *v; + _Py_identifier(msg); + _Py_identifier(filename); + _Py_identifier(lineno); + _Py_identifier(offset); + _Py_identifier(text); /* old style errors */ if (PyTuple_Check(err)) @@ -1326,11 +1334,11 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, /* new style errors. `err' is an instance */ - if (! (v = PyObject_GetAttrString(err, "msg"))) + if (! (v = _PyObject_GetAttrId(err, &PyId_msg))) goto finally; *message = v; - if (!(v = PyObject_GetAttrString(err, "filename"))) + if (!(v = _PyObject_GetAttrId(err, &PyId_filename))) goto finally; if (v == Py_None) *filename = NULL; @@ -1338,7 +1346,7 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, goto finally; Py_DECREF(v); - if (!(v = PyObject_GetAttrString(err, "lineno"))) + if (!(v = _PyObject_GetAttrId(err, &PyId_lineno))) goto finally; hold = PyLong_AsLong(v); Py_DECREF(v); @@ -1347,7 +1355,7 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, goto finally; *lineno = (int)hold; - if (!(v = PyObject_GetAttrString(err, "offset"))) + if (!(v = _PyObject_GetAttrId(err, &PyId_offset))) goto finally; if (v == Py_None) { *offset = -1; @@ -1362,7 +1370,7 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, *offset = (int)hold; } - if (!(v = PyObject_GetAttrString(err, "text"))) + if (!(v = _PyObject_GetAttrId(err, &PyId_text))) goto finally; if (v == Py_None) *text = NULL; @@ -1431,7 +1439,8 @@ handle_system_exit(void) goto done; if (PyExceptionInstance_Check(value)) { /* The error code should be in the `code' attribute. */ - PyObject *code = PyObject_GetAttrString(value, "code"); + _Py_identifier(code); + PyObject *code = _PyObject_GetAttrId(value, &PyId_code); if (code) { Py_DECREF(value); value = code; @@ -1588,6 +1597,7 @@ print_exception(PyObject *f, PyObject *value) else { PyObject* moduleName; char* className; + _Py_identifier(__module__); assert(PyExceptionClass_Check(type)); className = PyExceptionClass_Name(type); if (className != NULL) { @@ -1596,7 +1606,7 @@ print_exception(PyObject *f, PyObject *value) className = dot+1; } - moduleName = PyObject_GetAttrString(type, "__module__"); + moduleName = _PyObject_GetAttrId(type, &PyId___module__); if (moduleName == NULL || !PyUnicode_Check(moduleName)) { Py_XDECREF(moduleName); diff --git a/Python/sysmodule.c b/Python/sysmodule.c index f0aceada5f..5195a4a79f 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -79,8 +79,10 @@ sys_displayhook_unencodable(PyObject *outf, PyObject *o) PyObject *encoded, *escaped_str, *repr_str, *buffer, *result; char *stdout_encoding_str; int ret; + _Py_identifier(encoding); + _Py_identifier(buffer); - stdout_encoding = PyObject_GetAttrString(outf, "encoding"); + stdout_encoding = _PyObject_GetAttrId(outf, &PyId_encoding); if (stdout_encoding == NULL) goto error; stdout_encoding_str = _PyUnicode_AsString(stdout_encoding); @@ -97,7 +99,7 @@ sys_displayhook_unencodable(PyObject *outf, PyObject *o) if (encoded == NULL) goto error; - buffer = PyObject_GetAttrString(outf, "buffer"); + buffer = _PyObject_GetAttrId(outf, &PyId_buffer); if (buffer) { _Py_identifier(write); result = _PyObject_CallMethodId(buffer, &PyId_write, "(O)", encoded); @@ -1841,11 +1843,12 @@ sys_pyfile_write_unicode(PyObject *unicode, PyObject *file) { PyObject *writer = NULL, *args = NULL, *result = NULL; int err; + _Py_identifier(write); if (file == NULL) return -1; - writer = PyObject_GetAttrString(file, "write"); + writer = _PyObject_GetAttrId(file, &PyId_write); if (writer == NULL) goto error; -- cgit v1.2.1 From 9fde12ef0a3cbe4260897de13f054ec630456992 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 11 Oct 2011 21:55:01 +0200 Subject: Use PyUnicode_AsUnicodeAndSize() instead of PyUnicode_GET_SIZE() --- Python/getargs.c | 10 ++++++---- Python/import.c | 11 ++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 2c2db36193..f2cc9f4509 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -982,10 +982,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, STORE_SIZE(0); } else if (PyUnicode_Check(arg)) { - *p = PyUnicode_AS_UNICODE(arg); + Py_ssize_t len; + *p = PyUnicode_AsUnicodeAndSize(arg, &len); if (*p == NULL) RETURN_ERR_OCCURRED; - STORE_SIZE(PyUnicode_GET_SIZE(arg)); + STORE_SIZE(len); } else return converterr("str or None", arg, msgbuf, bufsize); @@ -995,10 +996,11 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (c == 'Z' && arg == Py_None) *p = NULL; else if (PyUnicode_Check(arg)) { - *p = PyUnicode_AS_UNICODE(arg); + Py_ssize_t len; + *p = PyUnicode_AsUnicodeAndSize(arg, &len); if (*p == NULL) RETURN_ERR_OCCURRED; - if (Py_UNICODE_strlen(*p) != PyUnicode_GET_SIZE(arg)) + if (Py_UNICODE_strlen(*p) != len) return converterr( "str without null character or None", arg, msgbuf, bufsize); diff --git a/Python/import.c b/Python/import.c index 3d6c6ed1d4..6f564a65da 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2282,6 +2282,8 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) WIN32_FIND_DATAW data; HANDLE h; int cmp; + wchar_t *wname; + Py_ssizet wname_len; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; @@ -2294,9 +2296,12 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) return 0; } FindClose(h); - cmp = wcsncmp(data.cFileName, - PyUnicode_AS_UNICODE(name), - PyUnicode_GET_SIZE(name)); + + wname = PyUnicode_AsUnicodeAndSize(name, &wname_len); + if (wname == NULL) + return -1; + + cmp = wcsncmp(data.cFileName, wname, wname_len); return cmp == 0; #elif defined(USE_CASE_OK_BYTES) int match; -- cgit v1.2.1 From a9a394e1adfc52461ed6e062282256b6f59e809b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 11 Oct 2011 22:11:42 +0200 Subject: Fix misuse of PyUnicode_GET_SIZE, use PyUnicode_GET_LENGTH instead --- Python/formatter_unicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 037880068a..fda79fc657 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -693,7 +693,7 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format) Py_ssize_t rpad; Py_ssize_t total; Py_ssize_t pos; - Py_ssize_t len = PyUnicode_GET_SIZE(value); + Py_ssize_t len = PyUnicode_GET_LENGTH(value); PyObject *result = NULL; int maxchar = 127; -- cgit v1.2.1 From f716b4e95cf727dc9fe4a592c38e86b73ca16c74 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 11 Oct 2011 22:27:13 +0200 Subject: Fix typo in import.c --- 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 6f564a65da..d937cc165a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2283,7 +2283,7 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) HANDLE h; int cmp; wchar_t *wname; - Py_ssizet wname_len; + Py_ssize_t wname_len; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; -- cgit v1.2.1 From f52a051081e30c3421e009d1369e4f6be081fd93 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 12 Oct 2011 02:54:14 +0200 Subject: PEP 3151 / issue #12555: reworking the OS and IO exception hierarchy. --- Python/errors.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 02f84b46ac..6e69d23c30 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -496,10 +496,11 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( return NULL; } - if (filenameObject != NULL) - v = Py_BuildValue("(iOO)", err, message, filenameObject); - else - v = Py_BuildValue("(iO)", err, message); + if (filenameObject == NULL) + filenameObject = Py_None; + /* This is the constructor signature for passing a Windows error code. + The POSIX translation will be figured out by the constructor. */ + v = Py_BuildValue("(iOOi)", 0, message, filenameObject, err); Py_DECREF(message); if (v != NULL) { -- cgit v1.2.1 From edb19b80f00cf42741fa66efdcab2f25a9fb3f08 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 12 Oct 2011 19:39:57 +0200 Subject: Instantiate the OS-related exception as soon as we raise it, so that "except" works properly. --- Python/errors.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 6e69d23c30..5988e1bf89 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -341,7 +341,7 @@ PyObject * PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) { PyObject *message; - PyObject *v; + PyObject *v, *args; int i = errno; #ifndef MS_WINDOWS char *s; @@ -410,14 +410,18 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) } if (filenameObject != NULL) - v = Py_BuildValue("(iOO)", i, message, filenameObject); + args = Py_BuildValue("(iOO)", i, message, filenameObject); else - v = Py_BuildValue("(iO)", i, message); + args = Py_BuildValue("(iO)", i, message); Py_DECREF(message); - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); + if (args != NULL) { + v = PyObject_Call(exc, args, NULL); + Py_DECREF(args); + if (v != NULL) { + PyErr_SetObject((PyObject *) Py_TYPE(v), v); + Py_DECREF(v); + } } #ifdef MS_WINDOWS LocalFree(s_buf); -- cgit v1.2.1 From a337ec1d9c574b5a5d2bca01ceb43cdead37f799 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 13 Oct 2011 23:25:03 +0200 Subject: convertsimple(): "str without bytes" => "str without characters" --- Python/getargs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index f2cc9f4509..77f27bebc9 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -961,8 +961,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, arg, msgbuf, bufsize); if (*p != NULL && sarg != NULL && (Py_ssize_t) strlen(*p) != len) return converterr( - c == 'z' ? "str without null bytes or None" - : "str without null bytes", + c == 'z' ? "str without null characters or None" + : "str without null characters", arg, msgbuf, bufsize); } break; @@ -1002,7 +1002,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, RETURN_ERR_OCCURRED; if (Py_UNICODE_strlen(*p) != len) return converterr( - "str without null character or None", + "str without null characters or None", arg, msgbuf, bufsize); } else return converterr(c == 'Z' ? "str or None" : "str", -- cgit v1.2.1 From da328a42858356139f9e6de860b802408ed76f5d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 14 Oct 2011 02:13:11 +0200 Subject: Issue #13088: Add shared Py_hexdigits constant to format a number into base 16 --- Python/codecs.c | 24 ++++++++++++------------ Python/traceback.c | 3 +-- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 79dfe89aba..006d288b70 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -11,6 +11,8 @@ Copyright (c) Corporation for National Research Initiatives. #include "Python.h" #include +const char *Py_hexdigits = "0123456789abcdef"; + /* --- Codec Registry ----------------------------------------------------- */ /* Import the standard encodings package which will register the first @@ -673,8 +675,6 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) } } -static const char *hexdigits = "0123456789abcdef"; - PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { #ifndef Py_UNICODE_WIDE @@ -731,22 +731,22 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) } if (c >= 0x00010000) { *outp++ = 'U'; - *outp++ = hexdigits[(c>>28)&0xf]; - *outp++ = hexdigits[(c>>24)&0xf]; - *outp++ = hexdigits[(c>>20)&0xf]; - *outp++ = hexdigits[(c>>16)&0xf]; - *outp++ = hexdigits[(c>>12)&0xf]; - *outp++ = hexdigits[(c>>8)&0xf]; + *outp++ = Py_hexdigits[(c>>28)&0xf]; + *outp++ = Py_hexdigits[(c>>24)&0xf]; + *outp++ = Py_hexdigits[(c>>20)&0xf]; + *outp++ = Py_hexdigits[(c>>16)&0xf]; + *outp++ = Py_hexdigits[(c>>12)&0xf]; + *outp++ = Py_hexdigits[(c>>8)&0xf]; } else if (c >= 0x100) { *outp++ = 'u'; - *outp++ = hexdigits[(c>>12)&0xf]; - *outp++ = hexdigits[(c>>8)&0xf]; + *outp++ = Py_hexdigits[(c>>12)&0xf]; + *outp++ = Py_hexdigits[(c>>8)&0xf]; } else *outp++ = 'x'; - *outp++ = hexdigits[(c>>4)&0xf]; - *outp++ = hexdigits[c&0xf]; + *outp++ = Py_hexdigits[(c>>4)&0xf]; + *outp++ = Py_hexdigits[c&0xf]; } restuple = Py_BuildValue("(On)", res, end); diff --git a/Python/traceback.c b/Python/traceback.c index 551f9d6228..44358ed78d 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -463,12 +463,11 @@ dump_decimal(int fd, int value) 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]; + buffer[len] = Py_hexdigits[value & 15]; value >>= 4; len++; } while (len < width || value); -- cgit v1.2.1 From f5ad3b280b43227eb0e3fa63d89490a58ba9c28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 14 Oct 2011 10:20:37 +0200 Subject: Rename _Py_identifier to _Py_IDENTIFIER. --- Python/Python-ast.c | 130 +++++++++++++++++++++++++-------------------------- Python/_warnings.c | 4 +- Python/ast.c | 2 +- Python/bltinmodule.c | 12 ++--- Python/ceval.c | 2 +- Python/codecs.c | 4 +- Python/errors.c | 2 +- Python/import.c | 12 ++--- Python/marshal.c | 6 +-- Python/pythonrun.c | 32 ++++++------- Python/sysmodule.c | 8 ++-- Python/traceback.c | 8 ++-- 12 files changed, 111 insertions(+), 111 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2ed36cd220..7c0d858d29 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -7,7 +7,7 @@ static PyTypeObject AST_type; static PyTypeObject *mod_type; static PyObject* ast2obj_mod(void*); static PyTypeObject *Module_type; -_Py_identifier(body); +_Py_IDENTIFIER(body); static char *Module_fields[]={ "body", }; @@ -24,18 +24,18 @@ static char *Suite_fields[]={ "body", }; static PyTypeObject *stmt_type; -_Py_identifier(lineno); -_Py_identifier(col_offset); +_Py_IDENTIFIER(lineno); +_Py_IDENTIFIER(col_offset); static char *stmt_attributes[] = { "lineno", "col_offset", }; static PyObject* ast2obj_stmt(void*); static PyTypeObject *FunctionDef_type; -_Py_identifier(name); -_Py_identifier(args); -_Py_identifier(decorator_list); -_Py_identifier(returns); +_Py_IDENTIFIER(name); +_Py_IDENTIFIER(args); +_Py_IDENTIFIER(decorator_list); +_Py_IDENTIFIER(returns); static char *FunctionDef_fields[]={ "name", "args", @@ -44,10 +44,10 @@ static char *FunctionDef_fields[]={ "returns", }; static PyTypeObject *ClassDef_type; -_Py_identifier(bases); -_Py_identifier(keywords); -_Py_identifier(starargs); -_Py_identifier(kwargs); +_Py_IDENTIFIER(bases); +_Py_IDENTIFIER(keywords); +_Py_IDENTIFIER(starargs); +_Py_IDENTIFIER(kwargs); static char *ClassDef_fields[]={ "name", "bases", @@ -58,12 +58,12 @@ static char *ClassDef_fields[]={ "decorator_list", }; static PyTypeObject *Return_type; -_Py_identifier(value); +_Py_IDENTIFIER(value); static char *Return_fields[]={ "value", }; static PyTypeObject *Delete_type; -_Py_identifier(targets); +_Py_IDENTIFIER(targets); static char *Delete_fields[]={ "targets", }; @@ -73,16 +73,16 @@ static char *Assign_fields[]={ "value", }; static PyTypeObject *AugAssign_type; -_Py_identifier(target); -_Py_identifier(op); +_Py_IDENTIFIER(target); +_Py_IDENTIFIER(op); static char *AugAssign_fields[]={ "target", "op", "value", }; static PyTypeObject *For_type; -_Py_identifier(iter); -_Py_identifier(orelse); +_Py_IDENTIFIER(iter); +_Py_IDENTIFIER(orelse); static char *For_fields[]={ "target", "iter", @@ -90,7 +90,7 @@ static char *For_fields[]={ "orelse", }; static PyTypeObject *While_type; -_Py_identifier(test); +_Py_IDENTIFIER(test); static char *While_fields[]={ "test", "body", @@ -103,21 +103,21 @@ static char *If_fields[]={ "orelse", }; static PyTypeObject *With_type; -_Py_identifier(items); +_Py_IDENTIFIER(items); static char *With_fields[]={ "items", "body", }; static PyTypeObject *Raise_type; -_Py_identifier(exc); -_Py_identifier(cause); +_Py_IDENTIFIER(exc); +_Py_IDENTIFIER(cause); static char *Raise_fields[]={ "exc", "cause", }; static PyTypeObject *Try_type; -_Py_identifier(handlers); -_Py_identifier(finalbody); +_Py_IDENTIFIER(handlers); +_Py_IDENTIFIER(finalbody); static char *Try_fields[]={ "body", "handlers", @@ -125,19 +125,19 @@ static char *Try_fields[]={ "finalbody", }; static PyTypeObject *Assert_type; -_Py_identifier(msg); +_Py_IDENTIFIER(msg); static char *Assert_fields[]={ "test", "msg", }; static PyTypeObject *Import_type; -_Py_identifier(names); +_Py_IDENTIFIER(names); static char *Import_fields[]={ "names", }; static PyTypeObject *ImportFrom_type; -_Py_identifier(module); -_Py_identifier(level); +_Py_IDENTIFIER(module); +_Py_IDENTIFIER(level); static char *ImportFrom_fields[]={ "module", "names", @@ -165,21 +165,21 @@ static char *expr_attributes[] = { }; static PyObject* ast2obj_expr(void*); static PyTypeObject *BoolOp_type; -_Py_identifier(values); +_Py_IDENTIFIER(values); static char *BoolOp_fields[]={ "op", "values", }; static PyTypeObject *BinOp_type; -_Py_identifier(left); -_Py_identifier(right); +_Py_IDENTIFIER(left); +_Py_IDENTIFIER(right); static char *BinOp_fields[]={ "left", "op", "right", }; static PyTypeObject *UnaryOp_type; -_Py_identifier(operand); +_Py_IDENTIFIER(operand); static char *UnaryOp_fields[]={ "op", "operand", @@ -196,19 +196,19 @@ static char *IfExp_fields[]={ "orelse", }; static PyTypeObject *Dict_type; -_Py_identifier(keys); +_Py_IDENTIFIER(keys); static char *Dict_fields[]={ "keys", "values", }; static PyTypeObject *Set_type; -_Py_identifier(elts); +_Py_IDENTIFIER(elts); static char *Set_fields[]={ "elts", }; static PyTypeObject *ListComp_type; -_Py_identifier(elt); -_Py_identifier(generators); +_Py_IDENTIFIER(elt); +_Py_IDENTIFIER(generators); static char *ListComp_fields[]={ "elt", "generators", @@ -219,7 +219,7 @@ static char *SetComp_fields[]={ "generators", }; static PyTypeObject *DictComp_type; -_Py_identifier(key); +_Py_IDENTIFIER(key); static char *DictComp_fields[]={ "key", "value", @@ -235,15 +235,15 @@ static char *Yield_fields[]={ "value", }; static PyTypeObject *Compare_type; -_Py_identifier(ops); -_Py_identifier(comparators); +_Py_IDENTIFIER(ops); +_Py_IDENTIFIER(comparators); static char *Compare_fields[]={ "left", "ops", "comparators", }; static PyTypeObject *Call_type; -_Py_identifier(func); +_Py_IDENTIFIER(func); static char *Call_fields[]={ "func", "args", @@ -252,12 +252,12 @@ static char *Call_fields[]={ "kwargs", }; static PyTypeObject *Num_type; -_Py_identifier(n); +_Py_IDENTIFIER(n); static char *Num_fields[]={ "n", }; static PyTypeObject *Str_type; -_Py_identifier(s); +_Py_IDENTIFIER(s); static char *Str_fields[]={ "s", }; @@ -267,15 +267,15 @@ static char *Bytes_fields[]={ }; static PyTypeObject *Ellipsis_type; static PyTypeObject *Attribute_type; -_Py_identifier(attr); -_Py_identifier(ctx); +_Py_IDENTIFIER(attr); +_Py_IDENTIFIER(ctx); static char *Attribute_fields[]={ "value", "attr", "ctx", }; static PyTypeObject *Subscript_type; -_Py_identifier(slice); +_Py_IDENTIFIER(slice); static char *Subscript_fields[]={ "value", "slice", @@ -287,7 +287,7 @@ static char *Starred_fields[]={ "ctx", }; static PyTypeObject *Name_type; -_Py_identifier(id); +_Py_IDENTIFIER(id); static char *Name_fields[]={ "id", "ctx", @@ -315,16 +315,16 @@ static PyTypeObject *Param_type; static PyTypeObject *slice_type; static PyObject* ast2obj_slice(void*); static PyTypeObject *Slice_type; -_Py_identifier(lower); -_Py_identifier(upper); -_Py_identifier(step); +_Py_IDENTIFIER(lower); +_Py_IDENTIFIER(upper); +_Py_IDENTIFIER(step); static char *Slice_fields[]={ "lower", "upper", "step", }; static PyTypeObject *ExtSlice_type; -_Py_identifier(dims); +_Py_IDENTIFIER(dims); static char *ExtSlice_fields[]={ "dims", }; @@ -380,7 +380,7 @@ static PyTypeObject *In_type; static PyTypeObject *NotIn_type; static PyTypeObject *comprehension_type; static PyObject* ast2obj_comprehension(void*); -_Py_identifier(ifs); +_Py_IDENTIFIER(ifs); static char *comprehension_fields[]={ "target", "iter", @@ -393,7 +393,7 @@ static char *excepthandler_attributes[] = { }; static PyObject* ast2obj_excepthandler(void*); static PyTypeObject *ExceptHandler_type; -_Py_identifier(type); +_Py_IDENTIFIER(type); static char *ExceptHandler_fields[]={ "type", "name", @@ -401,13 +401,13 @@ static char *ExceptHandler_fields[]={ }; static PyTypeObject *arguments_type; static PyObject* ast2obj_arguments(void*); -_Py_identifier(vararg); -_Py_identifier(varargannotation); -_Py_identifier(kwonlyargs); -_Py_identifier(kwarg); -_Py_identifier(kwargannotation); -_Py_identifier(defaults); -_Py_identifier(kw_defaults); +_Py_IDENTIFIER(vararg); +_Py_IDENTIFIER(varargannotation); +_Py_IDENTIFIER(kwonlyargs); +_Py_IDENTIFIER(kwarg); +_Py_IDENTIFIER(kwargannotation); +_Py_IDENTIFIER(defaults); +_Py_IDENTIFIER(kw_defaults); static char *arguments_fields[]={ "args", "vararg", @@ -420,8 +420,8 @@ static char *arguments_fields[]={ }; static PyTypeObject *arg_type; static PyObject* ast2obj_arg(void*); -_Py_identifier(arg); -_Py_identifier(annotation); +_Py_IDENTIFIER(arg); +_Py_IDENTIFIER(annotation); static char *arg_fields[]={ "arg", "annotation", @@ -434,15 +434,15 @@ static char *keyword_fields[]={ }; static PyTypeObject *alias_type; static PyObject* ast2obj_alias(void*); -_Py_identifier(asname); +_Py_IDENTIFIER(asname); static char *alias_fields[]={ "name", "asname", }; static PyTypeObject *withitem_type; static PyObject* ast2obj_withitem(void*); -_Py_identifier(context_expr); -_Py_identifier(optional_vars); +_Py_IDENTIFIER(context_expr); +_Py_IDENTIFIER(optional_vars); static char *withitem_fields[]={ "context_expr", "optional_vars", @@ -452,7 +452,7 @@ static char *withitem_fields[]={ static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { - _Py_identifier(_fields); + _Py_IDENTIFIER(_fields); Py_ssize_t i, numfields = 0; int res = -1; PyObject *key, *value, *fields; @@ -506,7 +506,7 @@ static PyObject * ast_type_reduce(PyObject *self, PyObject *unused) { PyObject *res; - _Py_identifier(__dict__); + _Py_IDENTIFIER(__dict__); PyObject *dict = _PyObject_GetAttrId(self, &PyId___dict__); if (dict == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) diff --git a/Python/_warnings.c b/Python/_warnings.c index ebc9cb808c..6fcc128fb6 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -18,7 +18,7 @@ static int check_matched(PyObject *obj, PyObject *arg) { PyObject *result; - _Py_identifier(match); + _Py_IDENTIFIER(match); int rc; if (obj == Py_None) @@ -247,7 +247,7 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject PyObject *f_stderr; PyObject *name; char lineno_str[128]; - _Py_identifier(__name__); + _Py_IDENTIFIER(__name__); PyOS_snprintf(lineno_str, sizeof(lineno_str), ":%d: ", lineno); diff --git a/Python/ast.c b/Python/ast.c index 987297924e..48aef4815d 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -527,7 +527,7 @@ static PyObject *parsestrplus(struct compiling *, const node *n, static identifier new_identifier(const char* n, PyArena *arena) { - _Py_identifier(normalize); + _Py_IDENTIFIER(normalize); PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); if (!id || PyUnicode_READY(id) == -1) return NULL; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9849df6f67..e68f02500f 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -32,8 +32,8 @@ const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; #endif -_Py_identifier(fileno); -_Py_identifier(flush); +_Py_IDENTIFIER(fileno); +_Py_IDENTIFIER(flush); static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) @@ -41,7 +41,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; - _Py_identifier(__prepare__); + _Py_IDENTIFIER(__prepare__); assert(args != NULL); if (!PyTuple_Check(args)) { @@ -1614,7 +1614,7 @@ builtin_input(PyObject *self, PyObject *args) char *stdin_encoding_str; PyObject *result; size_t len; - _Py_identifier(encoding); + _Py_IDENTIFIER(encoding); stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding); if (!stdin_encoding) @@ -1790,7 +1790,7 @@ builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) PyObject *callable; static char *kwlist[] = {"iterable", "key", "reverse", 0}; int reverse; - _Py_identifier(sort); + _Py_IDENTIFIER(sort); /* args 1-3 should match listsort in Objects/listobject.c */ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", @@ -1847,7 +1847,7 @@ builtin_vars(PyObject *self, PyObject *args) Py_INCREF(d); } else { - _Py_identifier(__dict__); + _Py_IDENTIFIER(__dict__); d = _PyObject_GetAttrId(v, &PyId___dict__); if (d == NULL) { PyErr_SetString(PyExc_TypeError, diff --git a/Python/ceval.c b/Python/ceval.c index 04d3df1500..543c6f2179 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -372,7 +372,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) void PyEval_ReInitThreads(void) { - _Py_identifier(_after_fork); + _Py_IDENTIFIER(_after_fork); PyObject *threading, *result; PyThreadState *tstate = PyThreadState_GET(); diff --git a/Python/codecs.c b/Python/codecs.c index 006d288b70..eca2b88bfb 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -467,8 +467,8 @@ PyObject *PyCodec_LookupError(const char *name) static void wrong_exception_type(PyObject *exc) { - _Py_identifier(__class__); - _Py_identifier(__name__); + _Py_IDENTIFIER(__class__); + _Py_IDENTIFIER(__name__); PyObject *type = _PyObject_GetAttrId(exc, &PyId___class__); if (type != NULL) { PyObject *name = _PyObject_GetAttrId(type, &PyId___name__); diff --git a/Python/errors.c b/Python/errors.c index 5988e1bf89..998bef6a67 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -712,7 +712,7 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc, void PyErr_WriteUnraisable(PyObject *obj) { - _Py_identifier(__module__); + _Py_IDENTIFIER(__module__); PyObject *f, *t, *v, *tb; PyErr_Fetch(&t, &v, &tb); f = PySys_GetObject("stderr"); diff --git a/Python/import.c b/Python/import.c index d937cc165a..6e3e0f181e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -154,7 +154,7 @@ static const struct filedescr _PyImport_StandardFiletab[] = { }; static PyObject *initstr = NULL; -_Py_identifier(__path__); +_Py_IDENTIFIER(__path__); /* Initialize things */ @@ -248,7 +248,7 @@ _PyImportHooks_Init(void) PySys_WriteStderr("# can't import zipimport\n"); } else { - _Py_identifier(zipimporter); + _Py_IDENTIFIER(zipimporter); PyObject *zipimporter = _PyObject_GetAttrId(zimpimport, &PyId_zipimporter); Py_DECREF(zimpimport); @@ -1802,7 +1802,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, /* sys.path_hooks import hook */ if (p_loader != NULL) { - _Py_identifier(find_module); + _Py_IDENTIFIER(find_module); PyObject *importer; importer = get_path_importer(path_importer_cache, @@ -2032,7 +2032,7 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, /* sys.meta_path import hook */ if (p_loader != NULL) { - _Py_identifier(find_module); + _Py_IDENTIFIER(find_module); PyObject *meta_path; meta_path = PySys_GetObject("meta_path"); @@ -2462,7 +2462,7 @@ load_module(PyObject *name, FILE *fp, PyObject *pathname, int type, PyObject *lo break; case IMP_HOOK: { - _Py_identifier(load_module); + _Py_IDENTIFIER(load_module); if (loader == NULL) { PyErr_SetString(PyExc_ImportError, "import hook without loader"); @@ -3227,7 +3227,7 @@ ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *name, } if (PyUnicode_READ_CHAR(item, 0) == '*') { PyObject *all; - _Py_identifier(__all__); + _Py_IDENTIFIER(__all__); Py_DECREF(item); /* See if the package defines __all__ */ if (recursive) diff --git a/Python/marshal.c b/Python/marshal.c index b8288d0c1a..98bbbaff6b 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -480,7 +480,7 @@ r_string(char *s, int n, RFILE *p) } } else { - _Py_identifier(read); + _Py_IDENTIFIER(read); PyObject *data = _PyObject_CallMethodId(p->readable, &PyId_read, "i", n); read = 0; @@ -1292,7 +1292,7 @@ marshal_dump(PyObject *self, PyObject *args) int version = Py_MARSHAL_VERSION; PyObject *s; PyObject *res; - _Py_identifier(write); + _Py_IDENTIFIER(write); if (!PyArg_ParseTuple(args, "OO|i:dump", &x, &f, &version)) return NULL; @@ -1321,7 +1321,7 @@ static PyObject * marshal_load(PyObject *self, PyObject *f) { PyObject *data, *result; - _Py_identifier(read); + _Py_IDENTIFIER(read); RFILE rf; /* diff --git a/Python/pythonrun.c b/Python/pythonrun.c index df0d1b34e1..0ce61a5558 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -141,7 +141,7 @@ get_codec_name(const char *encoding) { char *name_utf8, *name_str; PyObject *codec, *name = NULL; - _Py_identifier(name); + _Py_IDENTIFIER(name); codec = _PyCodec_Lookup(encoding); if (!codec) @@ -353,7 +353,7 @@ flush_std_files(void) PyObject *fout = PySys_GetObject("stdout"); PyObject *ferr = PySys_GetObject("stderr"); PyObject *tmp; - _Py_identifier(flush); + _Py_IDENTIFIER(flush); if (fout != NULL && fout != Py_None) { tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); @@ -807,9 +807,9 @@ create_stdio(PyObject* io, const char* newline; PyObject *line_buffering; int buffering, isatty; - _Py_identifier(open); - _Py_identifier(isatty); - _Py_identifier(TextIOWrapper); + _Py_IDENTIFIER(open); + _Py_IDENTIFIER(isatty); + _Py_IDENTIFIER(TextIOWrapper); /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper @@ -831,7 +831,7 @@ create_stdio(PyObject* io, goto error; if (buffering) { - _Py_identifier(raw); + _Py_IDENTIFIER(raw); raw = _PyObject_GetAttrId(buf, &PyId_raw); if (raw == NULL) goto error; @@ -1117,7 +1117,7 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename, PyCompilerFlags *flags PyArena *arena; char *ps1 = "", *ps2 = "", *enc = NULL; int errcode = 0; - _Py_identifier(encoding); + _Py_IDENTIFIER(encoding); if (fp == stdin) { /* Fetch encoding from sys.stdin */ @@ -1321,11 +1321,11 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, { long hold; PyObject *v; - _Py_identifier(msg); - _Py_identifier(filename); - _Py_identifier(lineno); - _Py_identifier(offset); - _Py_identifier(text); + _Py_IDENTIFIER(msg); + _Py_IDENTIFIER(filename); + _Py_IDENTIFIER(lineno); + _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(text); /* old style errors */ if (PyTuple_Check(err)) @@ -1439,7 +1439,7 @@ handle_system_exit(void) goto done; if (PyExceptionInstance_Check(value)) { /* The error code should be in the `code' attribute. */ - _Py_identifier(code); + _Py_IDENTIFIER(code); PyObject *code = _PyObject_GetAttrId(value, &PyId_code); if (code) { Py_DECREF(value); @@ -1597,7 +1597,7 @@ print_exception(PyObject *f, PyObject *value) else { PyObject* moduleName; char* className; - _Py_identifier(__module__); + _Py_IDENTIFIER(__module__); assert(PyExceptionClass_Check(type)); className = PyExceptionClass_Name(type); if (className != NULL) { @@ -1773,7 +1773,7 @@ flush_io(void) { PyObject *f, *r; PyObject *type, *value, *traceback; - _Py_identifier(flush); + _Py_IDENTIFIER(flush); /* Save the current exception */ PyErr_Fetch(&type, &value, &traceback); @@ -2220,7 +2220,7 @@ static void wait_for_thread_shutdown(void) { #ifdef WITH_THREAD - _Py_identifier(_shutdown); + _Py_IDENTIFIER(_shutdown); PyObject *result; PyThreadState *tstate = PyThreadState_GET(); PyObject *threading = PyMapping_GetItemString(tstate->interp->modules, diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 5195a4a79f..7a1933d994 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -79,8 +79,8 @@ sys_displayhook_unencodable(PyObject *outf, PyObject *o) PyObject *encoded, *escaped_str, *repr_str, *buffer, *result; char *stdout_encoding_str; int ret; - _Py_identifier(encoding); - _Py_identifier(buffer); + _Py_IDENTIFIER(encoding); + _Py_IDENTIFIER(buffer); stdout_encoding = _PyObject_GetAttrId(outf, &PyId_encoding); if (stdout_encoding == NULL) @@ -101,7 +101,7 @@ sys_displayhook_unencodable(PyObject *outf, PyObject *o) buffer = _PyObject_GetAttrId(outf, &PyId_buffer); if (buffer) { - _Py_identifier(write); + _Py_IDENTIFIER(write); result = _PyObject_CallMethodId(buffer, &PyId_write, "(O)", encoded); Py_DECREF(buffer); Py_DECREF(encoded); @@ -1843,7 +1843,7 @@ sys_pyfile_write_unicode(PyObject *unicode, PyObject *file) { PyObject *writer = NULL, *args = NULL, *result = NULL; int err; - _Py_identifier(write); + _Py_IDENTIFIER(write); if (file == NULL) return -1; diff --git a/Python/traceback.c b/Python/traceback.c index 44358ed78d..2f4653bce6 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -152,7 +152,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject * const char* filepath; Py_ssize_t len; PyObject* result; - _Py_identifier(open); + _Py_IDENTIFIER(open); filebytes = PyUnicode_EncodeFSDefault(filename); if (filebytes == NULL) { @@ -232,9 +232,9 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent) char buf[MAXPATHLEN+1]; int kind; void *data; - _Py_identifier(close); - _Py_identifier(open); - _Py_identifier(TextIOWrapper); + _Py_IDENTIFIER(close); + _Py_IDENTIFIER(open); + _Py_IDENTIFIER(TextIOWrapper); /* open the file */ if (filename == NULL) -- cgit v1.2.1 From 406e4d8f1d3d003e8754d9e65607a697e7f5c865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 14 Oct 2011 15:16:45 +0200 Subject: Port SetAttrString/HasAttrString to SetAttrId/GetAttrId. --- Python/Python-ast.c | 269 ++++++++++++++++++++++++++-------------------------- Python/_warnings.c | 32 +++---- Python/ceval.c | 6 +- Python/errors.c | 26 +++-- Python/pythonrun.c | 9 +- Python/sysmodule.c | 5 +- 6 files changed, 179 insertions(+), 168 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 7c0d858d29..3cfb8a87aa 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -593,6 +593,7 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) { int i, result; + _Py_IDENTIFIER(_attributes); PyObject *s, *l = PyTuple_New(num_fields); if (!l) return 0; @@ -604,7 +605,7 @@ static int add_attributes(PyTypeObject* type, char**attrs, int num_fields) } PyTuple_SET_ITEM(l, i, s); } - result = PyObject_SetAttrString((PyObject*)type, "_attributes", l) >= 0; + result = _PyObject_SetAttrId((PyObject*)type, &PyId__attributes, l) >= 0; Py_DECREF(l); return result; } @@ -2230,7 +2231,7 @@ ast2obj_mod(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Module.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2239,7 +2240,7 @@ ast2obj_mod(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Interactive.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2248,7 +2249,7 @@ ast2obj_mod(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Expression.body); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2257,7 +2258,7 @@ ast2obj_mod(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Suite.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2285,29 +2286,29 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_identifier(o->v.FunctionDef.name); if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_name, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_arguments(o->v.FunctionDef.args); if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.FunctionDef.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.FunctionDef.decorator_list, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "decorator_list", value) == + if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.FunctionDef.returns); if (!value) goto failed; - if (PyObject_SetAttrString(result, "returns", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) goto failed; Py_DECREF(value); break; @@ -2316,38 +2317,38 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_identifier(o->v.ClassDef.name); if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_name, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.bases, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "bases", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_bases, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.keywords, ast2obj_keyword); if (!value) goto failed; - if (PyObject_SetAttrString(result, "keywords", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.ClassDef.starargs); if (!value) goto failed; - if (PyObject_SetAttrString(result, "starargs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_starargs, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.ClassDef.kwargs); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwargs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kwargs, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ClassDef.decorator_list, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "decorator_list", value) == + if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) goto failed; Py_DECREF(value); @@ -2357,7 +2358,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Return.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -2366,7 +2367,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Delete.targets, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "targets", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_targets, value) == -1) goto failed; Py_DECREF(value); break; @@ -2375,12 +2376,12 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Assign.targets, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "targets", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_targets, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Assign.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -2389,17 +2390,17 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.AugAssign.target); if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_target, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_operator(o->v.AugAssign.op); if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_op, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.AugAssign.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -2408,22 +2409,22 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.For.target); if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_target, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.For.iter); if (!value) goto failed; - if (PyObject_SetAttrString(result, "iter", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.For.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.For.orelse, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) goto failed; Py_DECREF(value); break; @@ -2432,17 +2433,17 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.While.test); if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_test, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.While.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.While.orelse, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) goto failed; Py_DECREF(value); break; @@ -2451,17 +2452,17 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.If.test); if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_test, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.If.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.If.orelse, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) goto failed; Py_DECREF(value); break; @@ -2470,12 +2471,12 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.With.items, ast2obj_withitem); if (!value) goto failed; - if (PyObject_SetAttrString(result, "items", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_items, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.With.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2484,12 +2485,12 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Raise.exc); if (!value) goto failed; - if (PyObject_SetAttrString(result, "exc", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_exc, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Raise.cause); if (!value) goto failed; - if (PyObject_SetAttrString(result, "cause", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_cause, value) == -1) goto failed; Py_DECREF(value); break; @@ -2498,22 +2499,22 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Try.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Try.handlers, ast2obj_excepthandler); if (!value) goto failed; - if (PyObject_SetAttrString(result, "handlers", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_handlers, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Try.orelse, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Try.finalbody, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "finalbody", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_finalbody, value) == -1) goto failed; Py_DECREF(value); break; @@ -2522,12 +2523,12 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Assert.test); if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_test, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Assert.msg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "msg", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_msg, value) == -1) goto failed; Py_DECREF(value); break; @@ -2536,7 +2537,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Import.names, ast2obj_alias); if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_names, value) == -1) goto failed; Py_DECREF(value); break; @@ -2545,17 +2546,17 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_identifier(o->v.ImportFrom.module); if (!value) goto failed; - if (PyObject_SetAttrString(result, "module", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_module, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ImportFrom.names, ast2obj_alias); if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_names, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_int(o->v.ImportFrom.level); if (!value) goto failed; - if (PyObject_SetAttrString(result, "level", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_level, value) == -1) goto failed; Py_DECREF(value); break; @@ -2564,7 +2565,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Global.names, ast2obj_identifier); if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_names, value) == -1) goto failed; Py_DECREF(value); break; @@ -2573,7 +2574,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Nonlocal.names, ast2obj_identifier); if (!value) goto failed; - if (PyObject_SetAttrString(result, "names", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_names, value) == -1) goto failed; Py_DECREF(value); break; @@ -2582,7 +2583,7 @@ ast2obj_stmt(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Expr.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -2601,12 +2602,12 @@ ast2obj_stmt(void* _o) } value = ast2obj_int(o->lineno); if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0) goto failed; Py_DECREF(value); value = ast2obj_int(o->col_offset); if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0) goto failed; Py_DECREF(value); return result; @@ -2632,12 +2633,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_boolop(o->v.BoolOp.op); if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_op, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.BoolOp.values, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "values", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_values, value) == -1) goto failed; Py_DECREF(value); break; @@ -2646,17 +2647,17 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.BinOp.left); if (!value) goto failed; - if (PyObject_SetAttrString(result, "left", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_left, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_operator(o->v.BinOp.op); if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_op, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.BinOp.right); if (!value) goto failed; - if (PyObject_SetAttrString(result, "right", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_right, value) == -1) goto failed; Py_DECREF(value); break; @@ -2665,12 +2666,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_unaryop(o->v.UnaryOp.op); if (!value) goto failed; - if (PyObject_SetAttrString(result, "op", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_op, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.UnaryOp.operand); if (!value) goto failed; - if (PyObject_SetAttrString(result, "operand", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_operand, value) == -1) goto failed; Py_DECREF(value); break; @@ -2679,12 +2680,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_arguments(o->v.Lambda.args); if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Lambda.body); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; @@ -2693,17 +2694,17 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.IfExp.test); if (!value) goto failed; - if (PyObject_SetAttrString(result, "test", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_test, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.IfExp.body); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.IfExp.orelse); if (!value) goto failed; - if (PyObject_SetAttrString(result, "orelse", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1) goto failed; Py_DECREF(value); break; @@ -2712,12 +2713,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Dict.keys, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "keys", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_keys, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Dict.values, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "values", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_values, value) == -1) goto failed; Py_DECREF(value); break; @@ -2726,7 +2727,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Set.elts, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elts", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1) goto failed; Py_DECREF(value); break; @@ -2735,13 +2736,13 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.ListComp.elt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elt", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ListComp.generators, ast2obj_comprehension); if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1) goto failed; Py_DECREF(value); break; @@ -2750,13 +2751,13 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.SetComp.elt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elt", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.SetComp.generators, ast2obj_comprehension); if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1) goto failed; Py_DECREF(value); break; @@ -2765,18 +2766,18 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.DictComp.key); if (!value) goto failed; - if (PyObject_SetAttrString(result, "key", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_key, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.DictComp.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.DictComp.generators, ast2obj_comprehension); if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1) goto failed; Py_DECREF(value); break; @@ -2785,13 +2786,13 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.GeneratorExp.elt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elt", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elt, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.GeneratorExp.generators, ast2obj_comprehension); if (!value) goto failed; - if (PyObject_SetAttrString(result, "generators", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_generators, value) == -1) goto failed; Py_DECREF(value); break; @@ -2800,7 +2801,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Yield.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -2809,7 +2810,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Compare.left); if (!value) goto failed; - if (PyObject_SetAttrString(result, "left", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_left, value) == -1) goto failed; Py_DECREF(value); { @@ -2820,12 +2821,12 @@ ast2obj_expr(void* _o) PyList_SET_ITEM(value, i, ast2obj_cmpop((cmpop_ty)asdl_seq_GET(o->v.Compare.ops, i))); } if (!value) goto failed; - if (PyObject_SetAttrString(result, "ops", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ops, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Compare.comparators, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "comparators", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_comparators, value) == -1) goto failed; Py_DECREF(value); break; @@ -2834,27 +2835,27 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Call.func); if (!value) goto failed; - if (PyObject_SetAttrString(result, "func", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_func, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Call.args, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.Call.keywords, ast2obj_keyword); if (!value) goto failed; - if (PyObject_SetAttrString(result, "keywords", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_keywords, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Call.starargs); if (!value) goto failed; - if (PyObject_SetAttrString(result, "starargs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_starargs, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Call.kwargs); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwargs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kwargs, value) == -1) goto failed; Py_DECREF(value); break; @@ -2863,7 +2864,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_object(o->v.Num.n); if (!value) goto failed; - if (PyObject_SetAttrString(result, "n", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_n, value) == -1) goto failed; Py_DECREF(value); break; @@ -2872,7 +2873,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_string(o->v.Str.s); if (!value) goto failed; - if (PyObject_SetAttrString(result, "s", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_s, value) == -1) goto failed; Py_DECREF(value); break; @@ -2881,7 +2882,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_bytes(o->v.Bytes.s); if (!value) goto failed; - if (PyObject_SetAttrString(result, "s", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_s, value) == -1) goto failed; Py_DECREF(value); break; @@ -2894,17 +2895,17 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Attribute.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_identifier(o->v.Attribute.attr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "attr", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_attr, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.Attribute.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; @@ -2913,17 +2914,17 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Subscript.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_slice(o->v.Subscript.slice); if (!value) goto failed; - if (PyObject_SetAttrString(result, "slice", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_slice, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.Subscript.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; @@ -2932,12 +2933,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Starred.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.Starred.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; @@ -2946,12 +2947,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_identifier(o->v.Name.id); if (!value) goto failed; - if (PyObject_SetAttrString(result, "id", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_id, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.Name.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; @@ -2960,12 +2961,12 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.List.elts, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elts", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.List.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; @@ -2974,24 +2975,24 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.Tuple.elts, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "elts", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_elts, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr_context(o->v.Tuple.ctx); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ctx", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ctx, value) == -1) goto failed; Py_DECREF(value); break; } value = ast2obj_int(o->lineno); if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0) goto failed; Py_DECREF(value); value = ast2obj_int(o->col_offset); if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0) goto failed; Py_DECREF(value); return result; @@ -3044,17 +3045,17 @@ ast2obj_slice(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Slice.lower); if (!value) goto failed; - if (PyObject_SetAttrString(result, "lower", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_lower, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Slice.upper); if (!value) goto failed; - if (PyObject_SetAttrString(result, "upper", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_upper, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Slice.step); if (!value) goto failed; - if (PyObject_SetAttrString(result, "step", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_step, value) == -1) goto failed; Py_DECREF(value); break; @@ -3063,7 +3064,7 @@ ast2obj_slice(void* _o) if (!result) goto failed; value = ast2obj_list(o->v.ExtSlice.dims, ast2obj_slice); if (!value) goto failed; - if (PyObject_SetAttrString(result, "dims", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_dims, value) == -1) goto failed; Py_DECREF(value); break; @@ -3072,7 +3073,7 @@ ast2obj_slice(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.Index.value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); break; @@ -3218,17 +3219,17 @@ ast2obj_comprehension(void* _o) if (!result) return NULL; value = ast2obj_expr(o->target); if (!value) goto failed; - if (PyObject_SetAttrString(result, "target", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_target, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->iter); if (!value) goto failed; - if (PyObject_SetAttrString(result, "iter", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->ifs, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "ifs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_ifs, value) == -1) goto failed; Py_DECREF(value); return result; @@ -3254,29 +3255,29 @@ ast2obj_excepthandler(void* _o) if (!result) goto failed; value = ast2obj_expr(o->v.ExceptHandler.type); if (!value) goto failed; - if (PyObject_SetAttrString(result, "type", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_type, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_identifier(o->v.ExceptHandler.name); if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_name, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->v.ExceptHandler.body, ast2obj_stmt); if (!value) goto failed; - if (PyObject_SetAttrString(result, "body", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); break; } value = ast2obj_int(o->lineno); if (!value) goto failed; - if (PyObject_SetAttrString(result, "lineno", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_lineno, value) < 0) goto failed; Py_DECREF(value); value = ast2obj_int(o->col_offset); if (!value) goto failed; - if (PyObject_SetAttrString(result, "col_offset", value) < 0) + if (_PyObject_SetAttrId(result, &PyId_col_offset, value) < 0) goto failed; Py_DECREF(value); return result; @@ -3300,42 +3301,42 @@ ast2obj_arguments(void* _o) if (!result) return NULL; value = ast2obj_list(o->args, ast2obj_arg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "args", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_args, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_identifier(o->vararg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "vararg", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_vararg, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->varargannotation); if (!value) goto failed; - if (PyObject_SetAttrString(result, "varargannotation", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_varargannotation, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->kwonlyargs, ast2obj_arg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwonlyargs", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kwonlyargs, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_identifier(o->kwarg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwarg", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kwarg, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->kwargannotation); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kwargannotation", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kwargannotation, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->defaults, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "defaults", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_defaults, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_list(o->kw_defaults, ast2obj_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "kw_defaults", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_kw_defaults, value) == -1) goto failed; Py_DECREF(value); return result; @@ -3359,12 +3360,12 @@ ast2obj_arg(void* _o) if (!result) return NULL; value = ast2obj_identifier(o->arg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "arg", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_arg, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->annotation); if (!value) goto failed; - if (PyObject_SetAttrString(result, "annotation", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_annotation, value) == -1) goto failed; Py_DECREF(value); return result; @@ -3388,12 +3389,12 @@ ast2obj_keyword(void* _o) if (!result) return NULL; value = ast2obj_identifier(o->arg); if (!value) goto failed; - if (PyObject_SetAttrString(result, "arg", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_arg, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->value); if (!value) goto failed; - if (PyObject_SetAttrString(result, "value", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); return result; @@ -3417,12 +3418,12 @@ ast2obj_alias(void* _o) if (!result) return NULL; value = ast2obj_identifier(o->name); if (!value) goto failed; - if (PyObject_SetAttrString(result, "name", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_name, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_identifier(o->asname); if (!value) goto failed; - if (PyObject_SetAttrString(result, "asname", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_asname, value) == -1) goto failed; Py_DECREF(value); return result; @@ -3446,12 +3447,12 @@ ast2obj_withitem(void* _o) if (!result) return NULL; value = ast2obj_expr(o->context_expr); if (!value) goto failed; - if (PyObject_SetAttrString(result, "context_expr", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_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) + if (_PyObject_SetAttrId(result, &PyId_optional_vars, value) == -1) goto failed; Py_DECREF(value); return result; diff --git a/Python/_warnings.c b/Python/_warnings.c index 6fcc128fb6..5846426531 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -654,8 +654,9 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) return NULL; if (module_globals) { - static PyObject *get_source_name = NULL; - static PyObject *splitlines_name = NULL; + _Py_IDENTIFIER(get_source); + _Py_IDENTIFIER(splitlines); + PyObject *tmp; PyObject *loader; PyObject *module_name; PyObject *source; @@ -663,16 +664,12 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) PyObject *source_line; PyObject *returned; - if (get_source_name == NULL) { - get_source_name = PyUnicode_InternFromString("get_source"); - if (!get_source_name) - return NULL; - } - if (splitlines_name == NULL) { - splitlines_name = PyUnicode_InternFromString("splitlines"); - if (!splitlines_name) - return NULL; - } + if ((tmp = _PyUnicode_FromId(&PyId_get_source)) == NULL) + return NULL; + Py_DECREF(tmp); + if ((tmp = _PyUnicode_FromId(&PyId_splitlines)) == NULL) + return NULL; + Py_DECREF(tmp); /* Check/get the requisite pieces needed for the loader. */ loader = PyDict_GetItemString(module_globals, "__loader__"); @@ -682,11 +679,11 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) goto standard_call; /* Make sure the loader implements the optional get_source() method. */ - if (!PyObject_HasAttrString(loader, "get_source")) + if (!_PyObject_HasAttrId(loader, &PyId_get_source)) goto standard_call; /* Call get_source() to get the source code. */ - source = PyObject_CallMethodObjArgs(loader, get_source_name, - module_name, NULL); + source = PyObject_CallMethodObjArgs(loader, PyId_get_source.object, + module_name, NULL); if (!source) return NULL; else if (source == Py_None) { @@ -695,8 +692,9 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) } /* Split the source into lines. */ - source_list = PyObject_CallMethodObjArgs(source, splitlines_name, - NULL); + source_list = PyObject_CallMethodObjArgs(source, + PyId_splitlines.object, + NULL); Py_DECREF(source); if (!source_list) return NULL; diff --git a/Python/ceval.c b/Python/ceval.c index 543c6f2179..8d980fdc93 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4422,7 +4422,9 @@ import_from(PyObject *v, PyObject *name) static int import_all_from(PyObject *locals, PyObject *v) { - PyObject *all = PyObject_GetAttrString(v, "__all__"); + _Py_IDENTIFIER(__all__); + _Py_IDENTIFIER(__dict__); + PyObject *all = _PyObject_GetAttrId(v, &PyId___all__); PyObject *dict, *name, *value; int skip_leading_underscores = 0; int pos, err; @@ -4431,7 +4433,7 @@ import_all_from(PyObject *locals, PyObject *v) if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; /* Unexpected error */ PyErr_Clear(); - dict = PyObject_GetAttrString(v, "__dict__"); + dict = _PyObject_GetAttrId(v, &PyId___dict__); if (dict == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; diff --git a/Python/errors.c b/Python/errors.c index 998bef6a67..d62648ba3a 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -780,6 +780,12 @@ void PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) { PyObject *exc, *v, *tb, *tmp; + _Py_IDENTIFIER(filename); + _Py_IDENTIFIER(lineno); + _Py_IDENTIFIER(msg); + _Py_IDENTIFIER(offset); + _Py_IDENTIFIER(print_file_and_line); + _Py_IDENTIFIER(text); /* add attributes for the line number and filename for the error */ PyErr_Fetch(&exc, &v, &tb); @@ -790,7 +796,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) if (tmp == NULL) PyErr_Clear(); else { - if (PyObject_SetAttrString(v, "lineno", tmp)) + if (_PyObject_SetAttrId(v, &PyId_lineno, tmp)) PyErr_Clear(); Py_DECREF(tmp); } @@ -799,7 +805,7 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) if (tmp == NULL) PyErr_Clear(); else { - if (PyObject_SetAttrString(v, "offset", tmp)) + if (_PyObject_SetAttrId(v, &PyId_offset, tmp)) PyErr_Clear(); Py_DECREF(tmp); } @@ -809,35 +815,35 @@ PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) if (tmp == NULL) PyErr_Clear(); else { - if (PyObject_SetAttrString(v, "filename", tmp)) + if (_PyObject_SetAttrId(v, &PyId_filename, tmp)) PyErr_Clear(); Py_DECREF(tmp); } tmp = PyErr_ProgramText(filename, lineno); if (tmp) { - if (PyObject_SetAttrString(v, "text", tmp)) + if (_PyObject_SetAttrId(v, &PyId_text, tmp)) PyErr_Clear(); Py_DECREF(tmp); } } - if (PyObject_SetAttrString(v, "offset", Py_None)) { + if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) { PyErr_Clear(); } if (exc != PyExc_SyntaxError) { - if (!PyObject_HasAttrString(v, "msg")) { + if (!_PyObject_HasAttrId(v, &PyId_msg)) { tmp = PyObject_Str(v); if (tmp) { - if (PyObject_SetAttrString(v, "msg", tmp)) + if (_PyObject_SetAttrId(v, &PyId_msg, tmp)) PyErr_Clear(); Py_DECREF(tmp); } else { PyErr_Clear(); } } - if (!PyObject_HasAttrString(v, "print_file_and_line")) { - if (PyObject_SetAttrString(v, "print_file_and_line", - Py_None)) + if (!_PyObject_HasAttrId(v, &PyId_print_file_and_line)) { + if (_PyObject_SetAttrId(v, &PyId_print_file_and_line, + Py_None)) PyErr_Clear(); } } diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 0ce61a5558..a6e7c46568 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -810,6 +810,8 @@ create_stdio(PyObject* io, _Py_IDENTIFIER(open); _Py_IDENTIFIER(isatty); _Py_IDENTIFIER(TextIOWrapper); + _Py_IDENTIFIER(name); + _Py_IDENTIFIER(mode); /* stdin is always opened in buffered mode, first because it shouldn't make a difference in common use cases, second because TextIOWrapper @@ -842,7 +844,7 @@ create_stdio(PyObject* io, } text = PyUnicode_FromString(name); - if (text == NULL || PyObject_SetAttrString(raw, "name", text) < 0) + if (text == NULL || _PyObject_SetAttrId(raw, &PyId_name, text) < 0) goto error; res = _PyObject_CallMethodId(raw, &PyId_isatty, ""); if (res == NULL) @@ -879,7 +881,7 @@ create_stdio(PyObject* io, else mode = "r"; text = PyUnicode_FromString(mode); - if (!text || PyObject_SetAttrString(stream, "mode", text) < 0) + if (!text || _PyObject_SetAttrId(stream, &PyId_mode, text) < 0) goto error; Py_CLEAR(text); return stream; @@ -1547,6 +1549,7 @@ print_exception(PyObject *f, PyObject *value) { int err = 0; PyObject *type, *tb; + _Py_IDENTIFIER(print_file_and_line); if (!PyExceptionInstance_Check(value)) { PyFile_WriteString("TypeError: print_exception(): Exception expected for value, ", f); @@ -1562,7 +1565,7 @@ print_exception(PyObject *f, PyObject *value) if (tb && tb != Py_None) err = PyTraceBack_Print(tb, f); if (err == 0 && - PyObject_HasAttrString(value, "print_file_and_line")) + _PyObject_HasAttrId(value, &PyId_print_file_and_line)) { PyObject *message; const char *filename, *text; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 7a1933d994..6911c9aef6 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -139,6 +139,7 @@ sys_displayhook(PyObject *self, PyObject *o) PyObject *modules = interp->modules; PyObject *builtins = PyDict_GetItemString(modules, "builtins"); int err; + _Py_IDENTIFIER(_); if (builtins == NULL) { PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); @@ -152,7 +153,7 @@ sys_displayhook(PyObject *self, PyObject *o) Py_INCREF(Py_None); return Py_None; } - if (PyObject_SetAttrString(builtins, "_", Py_None) != 0) + if (_PyObject_SetAttrId(builtins, &PyId__, Py_None) != 0) return NULL; outf = PySys_GetObject("stdout"); if (outf == NULL || outf == Py_None) { @@ -174,7 +175,7 @@ sys_displayhook(PyObject *self, PyObject *o) } if (PyFile_WriteString("\n", outf) != 0) return NULL; - if (PyObject_SetAttrString(builtins, "_", o) != 0) + if (_PyObject_SetAttrId(builtins, &PyId__, o) != 0) return NULL; Py_INCREF(Py_None); return Py_None; -- cgit v1.2.1 From 5263d9e0be0bf742276426378f96f8b6e6687872 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 17 Oct 2011 19:28:44 +0200 Subject: Issue #13146: Writing a pyc file is now atomic under POSIX. --- Python/import.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 6e3e0f181e..0db7e43d29 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1284,7 +1284,8 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, #ifdef MS_WINDOWS int fd; #else - PyObject *cpathbytes; + PyObject *cpathbytes, *cpathbytes_tmp; + Py_ssize_t cpathbytes_len; #endif PyObject *dirname; Py_UCS4 *dirsep; @@ -1345,13 +1346,25 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, else fp = NULL; #else + /* Under POSIX, we first write to a tmp file and then take advantage + of atomic renaming. */ cpathbytes = PyUnicode_EncodeFSDefault(cpathname); if (cpathbytes == NULL) { PyErr_Clear(); return; } + cpathbytes_len = PyBytes_GET_SIZE(cpathbytes); + cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 4); + if (cpathbytes_tmp == NULL) { + Py_DECREF(cpathbytes); + PyErr_Clear(); + return; + } + memcpy(PyBytes_AS_STRING(cpathbytes_tmp), PyBytes_AS_STRING(cpathbytes), + cpathbytes_len); + memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, ".tmp", 4); - fp = open_exclusive(PyBytes_AS_STRING(cpathbytes), mode); + fp = open_exclusive(PyBytes_AS_STRING(cpathbytes_tmp), mode); #endif if (fp == NULL) { if (Py_VerboseFlag) @@ -1359,6 +1372,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, "# can't create %R\n", cpathname); #ifndef MS_WINDOWS Py_DECREF(cpathbytes); + Py_DECREF(cpathbytes_tmp); #endif return; } @@ -1366,6 +1380,11 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, /* First write a 0 for mtime */ PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); + fflush(fp); + /* Now write the true mtime */ + fseek(fp, 4L, 0); + assert(mtime < LONG_MAX); + PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); if (fflush(fp) != 0 || ferror(fp)) { if (Py_VerboseFlag) PySys_FormatStderr("# can't write %R\n", cpathname); @@ -1374,20 +1393,28 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, #ifdef MS_WINDOWS (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname)); #else - (void) unlink(PyBytes_AS_STRING(cpathbytes)); + (void) unlink(PyBytes_AS_STRING(cpathbytes_tmp)); Py_DECREF(cpathbytes); + Py_DECREF(cpathbytes_tmp); #endif return; } + fclose(fp); + /* Under POSIX, do an atomic rename */ #ifndef MS_WINDOWS + if (rename(PyBytes_AS_STRING(cpathbytes_tmp), + PyBytes_AS_STRING(cpathbytes))) { + if (Py_VerboseFlag) + PySys_FormatStderr("# can't write %R\n", cpathname); + /* Don't keep tmp file */ + unlink(PyBytes_AS_STRING(cpathbytes_tmp)); + Py_DECREF(cpathbytes); + Py_DECREF(cpathbytes_tmp); + return; + } Py_DECREF(cpathbytes); + Py_DECREF(cpathbytes_tmp); #endif - /* Now write the true mtime */ - fseek(fp, 4L, 0); - assert(mtime < LONG_MAX); - PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); - fflush(fp); - fclose(fp); if (Py_VerboseFlag) PySys_FormatStderr("# wrote %R\n", cpathname); } -- cgit v1.2.1 From f8ba1a5cbeb56fe6ac204f3bdef184156b20aa4d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 17 Oct 2011 20:18:58 +0200 Subject: Instantiate the OS-related exception as soon as we raise it, so that "except" works properly. PyErr_SetFromErrnoWithFilenameObject() was already fixed by the changeset 793c75177d28. This commit fixes PyErr_SetExcFromWindowsErrWithFilenameObject(), used on Windows. --- Python/errors.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index d62648ba3a..cd0f68dff4 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -468,7 +468,7 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( int len; WCHAR *s_buf = NULL; /* Free via LocalFree */ PyObject *message; - PyObject *v; + PyObject *args, *v; DWORD err = (DWORD)ierr; if (err==0) err = GetLastError(); len = FormatMessageW( @@ -504,12 +504,16 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( filenameObject = Py_None; /* This is the constructor signature for passing a Windows error code. The POSIX translation will be figured out by the constructor. */ - v = Py_BuildValue("(iOOi)", 0, message, filenameObject, err); + args = Py_BuildValue("(iOOi)", 0, message, filenameObject, err); Py_DECREF(message); - if (v != NULL) { - PyErr_SetObject(exc, v); - Py_DECREF(v); + if (args != NULL) { + v = PyObject_Call(exc, args, NULL); + Py_DECREF(args); + if (v != NULL) { + PyErr_SetObject((PyObject *) Py_TYPE(v), v); + Py_DECREF(v); + } } LocalFree(s_buf); return NULL; -- cgit v1.2.1 From 9bde2716a2b2d48153a8e2bb99db27e7929a1e92 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 18 Oct 2011 21:21:00 +0200 Subject: Issue #12281: Rewrite the MBCS codec to handle correctly replace and ignore error handlers on all Windows versions. The MBCS codec is now supporting all error handlers, instead of only replace to encode and ignore to decode. --- Python/pythonrun.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a6e7c46568..0f2f0501cd 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -67,7 +67,7 @@ static void initsigs(void); static void call_py_exitfuncs(void); static void wait_for_thread_shutdown(void); static void call_ll_exitfuncs(void); -extern void _PyUnicode_Init(void); +extern int _PyUnicode_Init(void); extern void _PyUnicode_Fini(void); extern int _PyLong_Init(void); extern void PyLong_Fini(void); @@ -261,7 +261,8 @@ Py_InitializeEx(int install_sigs) Py_FatalError("Py_Initialize: can't make modules_reloading dictionary"); /* Init Unicode implementation; relies on the codec registry */ - _PyUnicode_Init(); + if (_PyUnicode_Init() < 0) + Py_FatalError("Py_Initialize: can't initialize unicode"); bimod = _PyBuiltin_Init(); if (bimod == NULL) -- cgit v1.2.1 From 787a4931e7a65741deb81c532dfb184af13a0e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 17:29:08 +0200 Subject: Reformulate make_compiled_pathname in terms of unicode objects. --- Python/import.c | 177 +++++++++++++++++++------------------------------------- 1 file changed, 61 insertions(+), 116 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 0db7e43d29..1101c920f5 100644 --- a/Python/import.c +++ b/Python/import.c @@ -904,6 +904,25 @@ rightmost_sep(Py_UCS4 *s) return found; } +/* Like rightmost_sep, but operate on unicode objects. */ +static Py_ssize_t +rightmost_sep_obj(PyObject* o) +{ + Py_ssize_t found, i; + Py_UCS4 c; + for (found = -1, i = 0; i < PyUnicode_GET_LENGTH(o); i++) { + c = PyUnicode_READ_CHAR(o, i); + if (c == SEP +#ifdef ALTSEP + || c == ALTSEP +#endif + ) + { + found = i; + } + } + return found; +} /* Given a pathname for a Python source file, fill a buffer with the pathname for the corresponding compiled file. Return the pathname @@ -915,123 +934,49 @@ rightmost_sep(Py_UCS4 *s) static PyObject* make_compiled_pathname(PyObject *pathstr, int debug) { - Py_UCS4 *pathname; - Py_UCS4 buf[MAXPATHLEN]; - size_t buflen = (size_t)MAXPATHLEN; - size_t len; - size_t i, save; - Py_UCS4 *pos; - int sep = SEP; - - pathname = PyUnicode_AsUCS4Copy(pathstr); - if (!pathname) - return NULL; - len = Py_UCS4_strlen(pathname); - - /* Sanity check that the buffer has roughly enough space to hold what - will eventually be the full path to the compiled file. The 5 extra - bytes include the slash afer __pycache__, the two extra dots, the - extra trailing character ('c' or 'o') and null. This isn't exact - because the contents of the buffer can affect how many actual - characters of the string get into the buffer. We'll do a final - sanity check before writing the extension to ensure we do not - overflow the buffer. - */ - if (len + Py_UCS4_strlen(CACHEDIR_UNICODE) + Py_UCS4_strlen(PYC_TAG_UNICODE) + 5 > buflen) { - PyMem_Free(pathname); - return NULL; - } - - /* Find the last path separator and copy everything from the start of - the source string up to and including the separator. - */ - pos = rightmost_sep(pathname); - if (pos == NULL) { - i = 0; - } - else { - sep = *pos; - i = pos - pathname + 1; - Py_UCS4_strncpy(buf, pathname, i); - } - - save = i; - buf[i++] = '\0'; - /* Add __pycache__/ */ - Py_UCS4_strcat(buf, CACHEDIR_UNICODE); - i += Py_UCS4_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. - */ - Py_UCS4_strcat(buf, pathname + save); - pos = Py_UCS4_strrchr(buf + i, '.'); - if (pos != NULL) - *++pos = '\0'; - - /* pathname is not used from here on. */ - PyMem_Free(pathname); - - Py_UCS4_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 - fills the buffer? By appending 4 more characters onto the string - here, we could overrun the buffer. - - As a simple example, let's say buflen=32 and the input string is - 'xxx.py'. strlen() would be 6 and the test above would yield: - - (6 + 11 + 10 + 5 == 32) > 32 - - which is false and so the name mangling would continue. This would - be fine because we'd end up with this string in buf: - - __pycache__/xxx.cpython-32.pyc\0 - - strlen(of that) == 30 + the nul fits inside a 32 character buffer. - We can even handle an input string of say 'xxxxx' above because - that's (5 + 11 + 10 + 5 == 31) > 32 which is also false. Name - mangling that yields: - - __pycache__/xxxxxcpython-32.pyc\0 - - which is 32 characters including the nul, and thus fits in the - buffer. However, an input string of 'xxxxxx' would yield a result - string of: - - __pycache__/xxxxxxcpython-32.pyc\0 - - which is 33 characters long (including the nul), thus overflowing - the buffer, even though the first test would fail, i.e.: the input - string is also 6 characters long, so 32 > 32 is false. - - The reason the first test fails but we still overflow the buffer is - that the test above only expects to add one extra character to be - added to the extension, and here we're adding three (pyc). We - don't add the first dot, so that reclaims one of expected - positions, leaving us overflowing by 1 byte (3 extra - 1 reclaimed - dot - 1 expected extra == 1 overflowed). - - The best we can do is ensure that we still have enough room in the - target buffer before we write the extension. Because it's always - only the extension that can cause the overflow, and never the other - path bytes we've written, it's sufficient to just do one more test - here. Still, the assertion that follows can't hurt. - */ -#if 0 - printf("strlen(buf): %d; buflen: %d\n", (int)strlen(buf), (int)buflen); -#endif - len = Py_UCS4_strlen(buf); - if (len + 5 > buflen) + PyObject *result; + Py_ssize_t fname, ext, len, i, pos, taglen; + Py_ssize_t pycache_len = sizeof("__pycache__/") - 1; + int kind; + void *data; + + /* Compute the output string size. */ + len = PyUnicode_GET_LENGTH(pathstr); + /* If there is no separator, this returns -1, so + lastsep will be 0. */ + fname = rightmost_sep_obj(pathstr) + 1; + ext = fname - 1; + for(i = fname; i < len; i++) + if (PyUnicode_READ_CHAR(pathstr, i) == '.') + ext = i + 1; + if (ext < fname) + /* No dot in filename; use entire filename */ + ext = len; + + /* result = pathstr[:fname] + "__pycache__" + SEP + + pathstr[fname:ext] + tag + ".py[co]" */ + taglen = strlen(pyc_tag); + result = PyUnicode_New(ext + pycache_len + taglen + 4, + PyUnicode_MAX_CHAR_VALUE(pathstr)); + if (!result) return NULL; - buf[len] = '.'; len++; - buf[len] = 'p'; len++; - buf[len] = 'y'; len++; - buf[len] = debug ? 'c' : 'o'; len++; - assert(len <= buflen); - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, len); + kind = PyUnicode_KIND(result); + data = PyUnicode_DATA(result); + PyUnicode_CopyCharacters(result, 0, pathstr, 0, fname); + pos = fname; + for (i = 0; i < pycache_len - 1; i++) + PyUnicode_WRITE(kind, data, pos++, "__pycache__"[i]); + PyUnicode_WRITE(kind, data, pos++, SEP); + PyUnicode_CopyCharacters(result, pos, pathstr, + fname, ext - fname); + pos += ext - fname; + for (i = 0; pyc_tag[i]; i++) + PyUnicode_WRITE(kind, data, pos++, pyc_tag[i]); + PyUnicode_WRITE(kind, data, pos++, '.'); + PyUnicode_WRITE(kind, data, pos++, 'p'); + PyUnicode_WRITE(kind, data, pos++, 'y'); + PyUnicode_WRITE(kind, data, pos++, debug ? 'c' : 'o'); + return result; } -- cgit v1.2.1 From 17bab0f4a5891ac06360ae32cc1b1f9ab746cf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 17:35:46 +0200 Subject: Add ready checks for make_compiled_pathname. --- Python/import.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 1101c920f5..5dcaf3a40e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -929,7 +929,10 @@ rightmost_sep_obj(PyObject* o) for the compiled file, or NULL if there's no space in the buffer. Doesn't set an exception. - foo.py -> __pycache__/foo..pyc */ + foo.py -> __pycache__/foo..pyc + + pathstr is assumed to be "ready". +*/ static PyObject* make_compiled_pathname(PyObject *pathstr, int debug) @@ -1458,6 +1461,8 @@ load_source_module(PyObject *name, PyObject *pathname, FILE *fp) goto error; } #endif + if (PyUnicode_READY(pathname) < 0) + return NULL; cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag); if (cpathname != NULL) @@ -3949,6 +3954,9 @@ imp_cache_from_source(PyObject *self, PyObject *args, PyObject *kws) return NULL; } + if (PyUnicode_READY(pathname) < 0) + return NULL; + cpathname = make_compiled_pathname(pathname, debug); Py_DECREF(pathname); -- cgit v1.2.1 From ff4c4b6f318abc223cbae8920ee2286d111d8bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 18:05:06 +0200 Subject: Rewrite make_source_pathname using Unicode API. --- Python/import.c | 79 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 38 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 5dcaf3a40e..a20871efcc 100644 --- a/Python/import.c +++ b/Python/import.c @@ -906,11 +906,11 @@ rightmost_sep(Py_UCS4 *s) /* Like rightmost_sep, but operate on unicode objects. */ static Py_ssize_t -rightmost_sep_obj(PyObject* o) +rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end) { Py_ssize_t found, i; Py_UCS4 c; - for (found = -1, i = 0; i < PyUnicode_GET_LENGTH(o); i++) { + for (found = -1, i = start; i < end; i++) { c = PyUnicode_READ_CHAR(o, i); if (c == SEP #ifdef ALTSEP @@ -947,7 +947,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) len = PyUnicode_GET_LENGTH(pathstr); /* If there is no separator, this returns -1, so lastsep will be 0. */ - fname = rightmost_sep_obj(pathstr) + 1; + fname = rightmost_sep_obj(pathstr, 0, len) + 1; ext = fname - 1; for(i = fname; i < len; i++) if (PyUnicode_READ_CHAR(pathstr, i) == '.') @@ -992,63 +992,66 @@ make_compiled_pathname(PyObject *pathstr, int debug) (...)/__pycache__/foo..pyc -> (...)/foo.py */ static PyObject* -make_source_pathname(PyObject *pathobj) +make_source_pathname(PyObject *path) { - Py_UCS4 buf[MAXPATHLEN]; - Py_UCS4 *pathname; - Py_UCS4 *left, *right, *dot0, *dot1, sep; - size_t i, j; + Py_ssize_t left, right, dot0, dot1, len; + Py_ssize_t i, j; + PyObject *result; + int kind; + void *data; - if (PyUnicode_GET_LENGTH(pathobj) > MAXPATHLEN) - return NULL; - pathname = PyUnicode_AsUCS4Copy(pathobj); - if (!pathname) + len = PyUnicode_GET_LENGTH(path); + if (len > MAXPATHLEN) return NULL; /* 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. */ - right = rightmost_sep(pathname); - if (right == NULL) + right = rightmost_sep_obj(path, 0, len); + if (right == -1) return NULL; - sep = *right; - *right = '\0'; - left = rightmost_sep(pathname); - *right = sep; - if (left == NULL) - left = pathname; + left = rightmost_sep_obj(path, 0, right); + if (left == -1) + left = 0; else left++; - if (right-left != Py_UCS4_strlen(CACHEDIR_UNICODE) || - Py_UCS4_strncmp(left, CACHEDIR_UNICODE, right-left) != 0) - goto error; + if (right-left != sizeof(CACHEDIR)-1) + return NULL; + for (i = 0; i < sizeof(CACHEDIR)-1; i++) + if (PyUnicode_READ_CHAR(path, left+i) != CACHEDIR[i]) + return NULL; /* Now verify that the path component to the right of the last slash has two dots in it. */ - if ((dot0 = Py_UCS4_strchr(right + 1, '.')) == NULL) - goto error; - if ((dot1 = Py_UCS4_strchr(dot0 + 1, '.')) == NULL) - goto error; + dot0 = PyUnicode_FindChar(path, '.', right+1, len, 1); + if (dot0 < 0) + return NULL; + dot1 = PyUnicode_FindChar(path, '.', dot0+1, len, 1); + if (dot1 < 0) + return NULL; /* Too many dots? */ - if (Py_UCS4_strchr(dot1 + 1, '.') != NULL) - goto error; + if (PyUnicode_FindChar(path, '.', dot1+1, len, 1) != -1) + return NULL; /* This is a PEP 3147 path. Start by copying everything from the start of pathname up to and including the leftmost slash. Then copy the file's basename, removing the magic tag and adding a .py suffix. */ - Py_UCS4_strncpy(buf, pathname, (i=left-pathname)); - Py_UCS4_strncpy(buf+i, right+1, (j=dot0-right)); - buf[i+j] = 'p'; - buf[i+j+1] = 'y'; - PyMem_Free(pathname); - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buf, i+j+2); - error: - PyMem_Free(pathname); - return NULL; + result = PyUnicode_New(left + (dot0-right) + 2, + PyUnicode_MAX_CHAR_VALUE(path)); + if (!result) + return NULL; + kind = PyUnicode_KIND(result); + data = PyUnicode_DATA(result); + PyUnicode_CopyCharacters(result, 0, path, 0, (i = left)); + PyUnicode_CopyCharacters(result, left, path, right+1, + (j = dot0-right)); + PyUnicode_WRITE(kind, data, i+j, 'p'); + PyUnicode_WRITE(kind, data, i+j+1, 'y'); + return result; } /* Given a pathname for a Python source file, its time of last -- cgit v1.2.1 From c7e9dd65640704b9ef0174a6c5fc9d82fbebf492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 18:08:20 +0200 Subject: Drop unused macros. Use CACHEDIR consistently. --- Python/import.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index a20871efcc..ebaaeacebd 100644 --- a/Python/import.c +++ b/Python/import.c @@ -108,8 +108,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 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. + TAG 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) @@ -118,13 +118,9 @@ typedef unsigned short mode_t; #define MAGIC (3190 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" -static const Py_UCS4 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; -static const Py_UCS4 PYC_TAG_UNICODE[] = { - 'c', 'p', 'y', 't', 'h', 'o', 'n', '-', PY_MAJOR_VERSION + 48, PY_MINOR_VERSION + 48, '\0'}; #undef QUOTE #undef STRIFY #undef MAJOR @@ -939,7 +935,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) { PyObject *result; Py_ssize_t fname, ext, len, i, pos, taglen; - Py_ssize_t pycache_len = sizeof("__pycache__/") - 1; + Py_ssize_t pycache_len = sizeof(CACHEDIR) - 1; int kind; void *data; @@ -968,7 +964,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) PyUnicode_CopyCharacters(result, 0, pathstr, 0, fname); pos = fname; for (i = 0; i < pycache_len - 1; i++) - PyUnicode_WRITE(kind, data, pos++, "__pycache__"[i]); + PyUnicode_WRITE(kind, data, pos++, CACHEDIR[i]); PyUnicode_WRITE(kind, data, pos++, SEP); PyUnicode_CopyCharacters(result, pos, pathstr, fname, ext - fname); -- cgit v1.2.1 From 012400c9fe4281ff97e7dee256cd2a05649a54ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 18:41:56 +0200 Subject: Fix off-by-one error. --- 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 ebaaeacebd..736ce7717c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -955,7 +955,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) /* result = pathstr[:fname] + "__pycache__" + SEP + pathstr[fname:ext] + tag + ".py[co]" */ taglen = strlen(pyc_tag); - result = PyUnicode_New(ext + pycache_len + taglen + 4, + result = PyUnicode_New(ext + pycache_len + 1 + taglen + 4, PyUnicode_MAX_CHAR_VALUE(pathstr)); if (!result) return NULL; @@ -963,7 +963,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) data = PyUnicode_DATA(result); PyUnicode_CopyCharacters(result, 0, pathstr, 0, fname); pos = fname; - for (i = 0; i < pycache_len - 1; i++) + for (i = 0; i < pycache_len; i++) PyUnicode_WRITE(kind, data, pos++, CACHEDIR[i]); PyUnicode_WRITE(kind, data, pos++, SEP); PyUnicode_CopyCharacters(result, pos, pathstr, -- cgit v1.2.1 From 9d5ef173055b3857a637b716f029b0e81d172c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 23 Oct 2011 18:45:16 +0200 Subject: Rewrite find_module_path using unicode API. --- Python/import.c | 83 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 35 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 736ce7717c..e21ae39359 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1743,11 +1743,11 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, PyObject *path_hooks, PyObject *path_importer_cache, PyObject **p_path, PyObject **p_loader, struct filedescr **p_fd) { - Py_UCS4 buf[MAXPATHLEN+1]; - PyObject *path_unicode, *filename; - Py_ssize_t len; + PyObject *path_unicode, *filename = NULL; + Py_ssize_t len, pos; struct stat statbuf; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; + int result, addsep; if (PyUnicode_Check(path)) { Py_INCREF(path); @@ -1766,15 +1766,10 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, return -1; len = PyUnicode_GET_LENGTH(path_unicode); - if (!PyUnicode_AsUCS4(path_unicode, buf, Py_ARRAY_LENGTH(buf), 1)) { - Py_DECREF(path_unicode); - PyErr_Clear(); - return 0; + if (PyUnicode_FindChar(path_unicode, 0, 0, len, 1) != -1) { + result = 0; + goto out; /* path contains '\0' */ } - Py_DECREF(path_unicode); - - if (Py_UCS4_strlen(buf) != len) - return 0; /* path contains '\0' */ /* sys.path_hooks import hook */ if (p_loader != NULL) { @@ -1784,43 +1779,54 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, importer = get_path_importer(path_importer_cache, path_hooks, path); if (importer == NULL) { - return -1; + result = -1; + goto out; } /* Note: importer is a borrowed reference */ if (importer != Py_None) { PyObject *loader; loader = _PyObject_CallMethodId(importer, &PyId_find_module, "O", fullname); - if (loader == NULL) - return -1; /* error */ + if (loader == NULL) { + result = -1; /* error */ + goto out; + } if (loader != Py_None) { /* a loader was found */ *p_loader = loader; *p_fd = &importhookdescr; - return 2; + result = 2; + goto out; } Py_DECREF(loader); - return 0; + result = 0; + goto out; } } /* no hook was found, use builtin import */ - if (len > 0 && buf[len-1] != SEP + addsep = 0; + if (len > 0 && PyUnicode_READ_CHAR(path_unicode, len-1) != SEP #ifdef ALTSEP - && buf[len-1] != ALTSEP + && PyUnicode_READ_CHAR(path_unicode, len-1) != ALTSEP #endif ) - buf[len++] = SEP; - if (!PyUnicode_AsUCS4(name, buf+len, Py_ARRAY_LENGTH(buf)-len, 1)) { - PyErr_Clear(); - return 0; - } - len += PyUnicode_GET_LENGTH(name); - - filename = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - buf, len); - if (filename == NULL) - return -1; + addsep = 1; + filename = PyUnicode_New(len + PyUnicode_GET_LENGTH(name) + addsep, + Py_MAX(PyUnicode_MAX_CHAR_VALUE(path_unicode), + PyUnicode_MAX_CHAR_VALUE(name))); + if (filename == NULL) { + result = -1; + goto out; + } + PyUnicode_CopyCharacters(filename, 0, path_unicode, 0, len); + pos = len; + if (addsep) + PyUnicode_WRITE(PyUnicode_KIND(filename), + PyUnicode_DATA(filename), + pos++, SEP); + PyUnicode_CopyCharacters(filename, pos, name, 0, + PyUnicode_GET_LENGTH(name)); /* Check for package import (buf holds a directory name, and there's an __init__ module in that directory */ @@ -1832,14 +1838,16 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, match = case_ok(filename, 0, name); if (match < 0) { - Py_DECREF(filename); - return -1; + result = -1; + goto out; } if (match) { /* case matches */ if (find_init_module(filename)) { /* and has __init__.py */ *p_path = filename; + filename = NULL; *p_fd = &fd_package; - return 2; + result = 2; + goto out; } else { int err; @@ -1847,15 +1855,20 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, "Not importing directory %R: missing __init__.py", filename); if (err) { - Py_DECREF(filename); - return -1; + result = -1; + goto out; } } } } #endif *p_path = filename; - return 1; + filename = NULL; + result = 1; + out: + Py_DECREF(path_unicode); + Py_XDECREF(filename); + return result; } /* Find a module in search_path_list. For each path, try -- cgit v1.2.1 From 9ab76944255d2498c50789b1d0582aec1e417ad9 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 25 Oct 2011 00:21:02 +0200 Subject: Fix test_imp failure under Windows --- Python/import.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index e21ae39359..3842c63c2e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -938,12 +938,19 @@ make_compiled_pathname(PyObject *pathstr, int debug) Py_ssize_t pycache_len = sizeof(CACHEDIR) - 1; int kind; void *data; + Py_UCS4 lastsep; /* Compute the output string size. */ len = PyUnicode_GET_LENGTH(pathstr); /* If there is no separator, this returns -1, so - lastsep will be 0. */ + fname will be 0. */ fname = rightmost_sep_obj(pathstr, 0, len) + 1; + /* Windows: re-use the last separator character (/ or \\) when + appending the __pycache__ path. */ + if (fname > 0) + lastsep = PyUnicode_READ_CHAR(pathstr, fname -1); + else + lastsep = SEP; ext = fname - 1; for(i = fname; i < len; i++) if (PyUnicode_READ_CHAR(pathstr, i) == '.') @@ -965,7 +972,7 @@ make_compiled_pathname(PyObject *pathstr, int debug) pos = fname; for (i = 0; i < pycache_len; i++) PyUnicode_WRITE(kind, data, pos++, CACHEDIR[i]); - PyUnicode_WRITE(kind, data, pos++, SEP); + PyUnicode_WRITE(kind, data, pos++, lastsep); PyUnicode_CopyCharacters(result, pos, pathstr, fname, ext - fname); pos += ext - fname; -- cgit v1.2.1 From 7336fba07c5e34404a0d72c4b24e78a3d83ac1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 30 Oct 2011 09:07:07 +0100 Subject: Port PyImport_ReloadModule to Unicode API. --- Python/import.c | 60 +++++++++++++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 3842c63c2e..294eb2bb33 100644 --- a/Python/import.c +++ b/Python/import.c @@ -3359,8 +3359,8 @@ PyImport_ReloadModule(PyObject *m) PyObject *modules_reloading = interp->modules_reloading; PyObject *modules = PyImport_GetModuleDict(); PyObject *path_list = NULL, *loader = NULL, *existing_m = NULL; - PyObject *nameobj, *bufobj, *subnameobj; - Py_UCS4 *name = NULL, *subname; + PyObject *name, *bufobj, *subname; + Py_ssize_t subname_start; struct filedescr *fdp; FILE *fp = NULL; PyObject *newm = NULL; @@ -3376,45 +3376,39 @@ PyImport_ReloadModule(PyObject *m) "reload() argument must be module"); return NULL; } - nameobj = PyModule_GetNameObject(m); - if (nameobj == NULL || PyUnicode_READY(nameobj) == -1) + name = PyModule_GetNameObject(m); + if (name == NULL || PyUnicode_READY(name) == -1) return NULL; - if (m != PyDict_GetItem(modules, nameobj)) { + if (m != PyDict_GetItem(modules, name)) { PyErr_Format(PyExc_ImportError, "reload(): module %R not in sys.modules", - nameobj); - Py_DECREF(nameobj); + name); + Py_DECREF(name); return NULL; } - existing_m = PyDict_GetItem(modules_reloading, nameobj); + existing_m = PyDict_GetItem(modules_reloading, name); if (existing_m != NULL) { /* Due to a recursive reload, this module is already being reloaded. */ - Py_DECREF(nameobj); + Py_DECREF(name); Py_INCREF(existing_m); return existing_m; } - if (PyDict_SetItem(modules_reloading, nameobj, m) < 0) { - Py_DECREF(nameobj); + if (PyDict_SetItem(modules_reloading, name, m) < 0) { + Py_DECREF(name); return NULL; } - name = PyUnicode_AsUCS4Copy(nameobj); - if (!name) { - Py_DECREF(nameobj); - return NULL; - } - subname = Py_UCS4_strrchr(name, '.'); - if (subname == NULL) { - Py_INCREF(nameobj); - subnameobj = nameobj; + subname_start = PyUnicode_FindChar(name, '.', 0, + PyUnicode_GET_LENGTH(name), -1); + if (subname_start == -1) { + Py_INCREF(name); + subname = name; } else { PyObject *parentname, *parent; Py_ssize_t len; - len = subname - name; - parentname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - name, len); + parentname = PyUnicode_Substring(name, 0, subname_start); if (parentname == NULL) { goto error; } @@ -3430,16 +3424,15 @@ PyImport_ReloadModule(PyObject *m) path_list = _PyObject_GetAttrId(parent, &PyId___path__); if (path_list == NULL) PyErr_Clear(); - subname++; - len = PyUnicode_GET_LENGTH(nameobj) - (len + 1); - subnameobj = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - subname, len); + subname_start++; + len = PyUnicode_GET_LENGTH(name) - (subname_start + 1); + subname = PyUnicode_Substring(name, subname_start, len); } - if (subnameobj == NULL) + if (subname == NULL) goto error; - fdp = find_module(nameobj, subnameobj, path_list, + fdp = find_module(name, subname, path_list, &bufobj, &fp, &loader); - Py_DECREF(subnameobj); + Py_DECREF(subname); Py_XDECREF(path_list); if (fdp == NULL) { @@ -3447,7 +3440,7 @@ PyImport_ReloadModule(PyObject *m) goto error; } - newm = load_module(nameobj, fp, bufobj, fdp->type, loader); + newm = load_module(name, fp, bufobj, fdp->type, loader); Py_XDECREF(bufobj); Py_XDECREF(loader); @@ -3459,13 +3452,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_SetItem(modules, nameobj, m); + PyDict_SetItem(modules, name, m); } error: imp_modules_reloading_clear(); - Py_DECREF(nameobj); - PyMem_Free(name); + Py_DECREF(name); return newm; } -- cgit v1.2.1 From 2593ff3b46728f698ea5a5307fcc6263012b358b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 30 Oct 2011 23:50:02 +0100 Subject: Port import_module_level to Unicode API. --- Python/import.c | 164 +++++++++++++++++++++----------------------------------- 1 file changed, 61 insertions(+), 103 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 8e3aa4b921..03e9986126 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2753,8 +2753,7 @@ static PyObject *get_parent(PyObject *globals, int level); static PyObject *load_next(PyObject *mod, PyObject *altmod, PyObject *inputname, PyObject **p_outputname, - Py_UCS4 *buf, Py_ssize_t *p_buflen, - Py_ssize_t bufsize); + PyObject **p_prefix); static int mark_miss(PyObject *name); static int ensure_fromlist(PyObject *mod, PyObject *fromlist, PyObject *buf, int recursive); @@ -2767,11 +2766,11 @@ static PyObject * import_module_level(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) { - Py_UCS4 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; + PyObject *parent, *next, *inputname, *outputname; + PyObject *head = NULL; + PyObject *tail = NULL; + PyObject *prefix = NULL; + PyObject *result = NULL; Py_ssize_t sep, altsep; if (PyUnicode_READY(name)) @@ -2794,26 +2793,18 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, return NULL; } - parent = get_parent(globals, &parent_name, level); + parent = get_parent(globals, &prefix, level); if (parent == NULL) { return NULL; } - if (PyUnicode_READY(parent_name)) + if (PyUnicode_READY(prefix)) return NULL; - buflen = PyUnicode_GET_LENGTH(parent_name); - if (!PyUnicode_AsUCS4(parent_name, buf, Py_ARRAY_LENGTH(buf), 1)) { - Py_DECREF(parent_name); - PyErr_SetString(PyExc_ValueError, - "Module name too long"); - return NULL; - } - Py_DECREF(parent_name); head = load_next(parent, level < 0 ? Py_None : parent, name, &outputname, - buf, &buflen, bufsize); + &prefix); if (head == NULL) - return NULL; + goto out; tail = head; Py_INCREF(tail); @@ -2822,13 +2813,11 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, 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; - } + &prefix); + Py_CLEAR(tail); + Py_CLEAR(inputname); + if (next == NULL) + goto out; tail = next; if (outputname == NULL) { @@ -2840,10 +2829,8 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, /* If tail is Py_None, both get_parent and load_next found an empty module name: someone called __import__("") or doctored faulty bytecode */ - Py_DECREF(tail); - Py_DECREF(head); PyErr_SetString(PyExc_ValueError, "Empty module name"); - return NULL; + goto out; } if (fromlist != NULL) { @@ -2852,26 +2839,21 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, } if (fromlist == NULL) { - Py_DECREF(tail); - return head; - } - - Py_DECREF(head); - - ensure_name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - buf, Py_UCS4_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; + result = head; + Py_INCREF(result); + goto out; } - Py_DECREF(ensure_name); - return tail; + if (!ensure_fromlist(tail, fromlist, prefix, 0)) + goto out; + + result = tail; + Py_INCREF(result); + out: + Py_XDECREF(head); + Py_XDECREF(tail); + Py_XDECREF(prefix); + return result; } PyObject * @@ -3083,91 +3065,67 @@ return_none: static PyObject * load_next(PyObject *mod, PyObject *altmod, PyObject *inputname, PyObject **p_outputname, - Py_UCS4 *buf, Py_ssize_t *p_buflen, Py_ssize_t bufsize) + PyObject **p_prefix) { - Py_UCS4 *dot; + Py_ssize_t dot; Py_ssize_t len; - Py_UCS4 *p; - PyObject *fullname, *name, *result, *mark_name; - Py_UCS4 *nameuni; + PyObject *fullname, *name = NULL, *result; *p_outputname = NULL; - if (PyUnicode_GET_LENGTH(inputname) == 0) { + len = PyUnicode_GET_LENGTH(inputname); + if (len == 0) { /* completely empty module name should only happen in 'from . import' (or '__import__("")')*/ Py_INCREF(mod); return mod; } - nameuni = PyUnicode_AsUCS4Copy(inputname); - if (nameuni == NULL) - return NULL; - dot = Py_UCS4_strchr(nameuni, '.'); - if (dot != NULL) { - len = dot - nameuni; + dot = PyUnicode_FindChar(inputname, '.', 0, len, 1); + if (dot >= 0) { + len = dot; if (len == 0) { PyErr_SetString(PyExc_ValueError, "Empty module name"); goto error; } } - else - len = PyUnicode_GET_LENGTH(inputname); - if (*p_buflen+len+1 >= bufsize) { - PyErr_SetString(PyExc_ValueError, - "Module name too long"); + /* name = inputname[:len] */ + name = PyUnicode_Substring(inputname, 0, len); + if (name == NULL) goto error; - } - p = buf + *p_buflen; - if (p != buf) { - *p++ = '.'; - *p_buflen += 1; + if (PyUnicode_GET_LENGTH(*p_prefix)) { + /* fullname = prefix + "." + name */ + fullname = PyUnicode_FromFormat("%U.%U", *p_prefix, name); + if (fullname == NULL) + goto error; } - Py_UCS4_strncpy(p, nameuni, len); - p[len] = '\0'; - *p_buflen += len; - - fullname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - buf, *p_buflen); - if (fullname == NULL) - goto error; - name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - p, len); - if (name == NULL) { - Py_DECREF(fullname); - goto error; + else { + fullname = name; + Py_INCREF(fullname); } + result = import_submodule(mod, name, fullname); - Py_DECREF(fullname); + Py_DECREF(*p_prefix); + /* Transfer reference. */ + *p_prefix = 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, name, name); - Py_DECREF(name); if (result != NULL && result != Py_None) { - mark_name = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - buf, *p_buflen); - if (mark_name == NULL) { + if (mark_miss(*p_prefix) != 0) { Py_DECREF(result); goto error; } - if (mark_miss(mark_name) != 0) { - Py_DECREF(result); - Py_DECREF(mark_name); - goto error; - } - Py_DECREF(mark_name); - Py_UCS4_strncpy(buf, nameuni, len); - buf[len] = '\0'; - *p_buflen = len; + Py_DECREF(*p_prefix); + *p_prefix = name; + Py_INCREF(*p_prefix); } } - else - Py_DECREF(name); if (result == NULL) goto error; @@ -3178,20 +3136,20 @@ load_next(PyObject *mod, PyObject *altmod, goto error; } - if (dot != NULL) { - *p_outputname = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - dot+1, Py_UCS4_strlen(dot+1)); + if (dot >= 0) { + *p_outputname = PyUnicode_Substring(inputname, dot+1, + PyUnicode_GET_LENGTH(inputname)); if (*p_outputname == NULL) { Py_DECREF(result); goto error; } } - PyMem_Free(nameuni); + Py_DECREF(name); return result; error: - PyMem_Free(nameuni); + Py_XDECREF(name); return NULL; } -- cgit v1.2.1 From 3d8b582274811ae53e65578f812a633429268d52 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 31 Oct 2011 11:48:09 +0100 Subject: Issue #13226: Update sys.setdlopenflags() docstring Refer to os.RTLD_xxx constants instead of ctypes and DLFCN modules. --- Python/sysmodule.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6911c9aef6..ab0008e44c 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -775,9 +775,7 @@ interpreter loads extension modules. Among other things, this will enable\n\ a lazy resolving of symbols when importing a module, if called as\n\ sys.setdlopenflags(0). To share symbols across extension modules, call as\n\ sys.setdlopenflags(ctypes.RTLD_GLOBAL). Symbolic names for the flag modules\n\ -can be either found in the ctypes module, or in the DLFCN module. If DLFCN\n\ -is not available, it can be generated from /usr/include/dlfcn.h using the\n\ -h2py script."); +can be found in the os module (RTLD_xxx constants, e.g. os.RTLD_LAZY)."); static PyObject * sys_getdlopenflags(PyObject *self, PyObject *args) -- cgit v1.2.1 From 0c820a9c9584c838de7ba3abea17c76a03bd405b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Mon, 31 Oct 2011 20:47:31 +0100 Subject: Issue #13303: Fix a race condition in the bytecode file creation. --- Python/import.c | 50 ++++++++------------------------------------------ 1 file changed, 8 insertions(+), 42 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 03e9986126..701041b2f2 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1183,42 +1183,6 @@ parse_source_module(PyObject *pathname, FILE *fp) return co; } -/* Helper to open a bytecode file for writing in exclusive mode */ - -#ifndef MS_WINDOWS -static FILE * -open_exclusive(char *filename, mode_t mode) -{ -#if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC) - /* Use O_EXCL to avoid a race condition when another process tries to - write the same file. When that happens, our open() call fails, - which is just fine (since it's only a cache). - XXX If the file exists and is writable but the directory is not - writable, the file will never be written. Oh well. - */ - int fd; - (void) unlink(filename); - fd = open(filename, O_EXCL|O_CREAT|O_WRONLY|O_TRUNC -#ifdef O_BINARY - |O_BINARY /* necessary for Windows */ -#endif -#ifdef __VMS - , mode, "ctxt=bin", "shr=nil" -#else - , mode -#endif - ); - if (fd < 0) - return NULL; - return fdopen(fd, "wb"); -#else - /* Best we can do -- on Windows this can't happen anyway */ - return fopen(filename, "wb"); -#endif -} -#endif - - /* Write a compiled module to a file, placing the time of last modification of its source into the header. Errors are ignored, if a write error occurs an attempt is made to @@ -1234,15 +1198,13 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; #else - mode_t mode = srcstat->st_mode & ~S_IXUSR & ~S_IXGRP & ~S_IXOTH; mode_t dirmode = (srcstat->st_mode | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR | S_IWGRP | S_IWOTH); PyObject *dirbytes; #endif -#ifdef MS_WINDOWS int fd; -#else +#ifndef MS_WINDOWS PyObject *cpathbytes, *cpathbytes_tmp; Py_ssize_t cpathbytes_len; #endif @@ -1313,7 +1275,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, return; } cpathbytes_len = PyBytes_GET_SIZE(cpathbytes); - cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 4); + cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 6); if (cpathbytes_tmp == NULL) { Py_DECREF(cpathbytes); PyErr_Clear(); @@ -1321,9 +1283,13 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } memcpy(PyBytes_AS_STRING(cpathbytes_tmp), PyBytes_AS_STRING(cpathbytes), cpathbytes_len); - memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, ".tmp", 4); + memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, "XXXXXX", 6); - fp = open_exclusive(PyBytes_AS_STRING(cpathbytes_tmp), mode); + fd = mkstemp(PyBytes_AS_STRING(cpathbytes_tmp)); + if (0 <= fd) + fp = fdopen(fd, "wb"); + else + fp = NULL; #endif if (fp == NULL) { if (Py_VerboseFlag) -- cgit v1.2.1 From e30694e4817ae7ff2c1502e57ad2ea7f293dfe21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 4 Nov 2011 11:16:41 +0100 Subject: Port error handlers from Py_UNICODE indexing to code point indexing. --- Python/codecs.c | 123 +++++++++++++++++++++----------------------------------- 1 file changed, 46 insertions(+), 77 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index eca2b88bfb..47cdb20add 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -573,82 +573,72 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; + Py_ssize_t i, o; Py_ssize_t start; Py_ssize_t end; PyObject *res; - Py_UNICODE *p; - Py_UNICODE *startp; - Py_UNICODE *outp; + unsigned char *outp; int ressize; + Py_UCS4 ch; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; - startp = PyUnicode_AS_UNICODE(object); - for (p = startp+start, ressize = 0; p < startp+end; ++p) { - if (*p<10) + for (i = start, ressize = 0; i < end; ++i) { + /* object is guaranteed to be "ready" */ + ch = PyUnicode_READ_CHAR(object, i); + if (ch<10) ressize += 2+1+1; - else if (*p<100) + else if (ch<100) ressize += 2+2+1; - else if (*p<1000) + else if (ch<1000) ressize += 2+3+1; - else if (*p<10000) + else if (ch<10000) ressize += 2+4+1; -#ifndef Py_UNICODE_WIDE - else - ressize += 2+5+1; -#else - else if (*p<100000) + else if (ch<100000) ressize += 2+5+1; - else if (*p<1000000) + else if (ch<1000000) ressize += 2+6+1; else ressize += 2+7+1; -#endif } /* allocate replacement */ - res = PyUnicode_FromUnicode(NULL, ressize); + res = PyUnicode_New(ressize, 127); if (res == NULL) { Py_DECREF(object); return NULL; } + outp = PyUnicode_1BYTE_DATA(res); /* generate replacement */ - for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); - p < startp+end; ++p) { - Py_UNICODE c = *p; + for (i = start, o = 0; i < end; ++i) { + ch = PyUnicode_READ_CHAR(object, i); int digits; int base; *outp++ = '&'; *outp++ = '#'; - if (*p<10) { + if (ch<10) { digits = 1; base = 1; } - else if (*p<100) { + else if (ch<100) { digits = 2; base = 10; } - else if (*p<1000) { + else if (ch<1000) { digits = 3; base = 100; } - else if (*p<10000) { + else if (ch<10000) { digits = 4; base = 1000; } -#ifndef Py_UNICODE_WIDE - else { - digits = 5; - base = 10000; - } -#else - else if (*p<100000) { + else if (ch<100000) { digits = 5; base = 10000; } - else if (*p<1000000) { + else if (ch<1000000) { digits = 6; base = 100000; } @@ -656,10 +646,9 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) digits = 7; base = 1000000; } -#endif while (digits-->0) { - *outp++ = '0' + c/base; - c %= base; + *outp++ = '0' + ch/base; + ch %= base; base /= 10; } *outp++ = ';'; @@ -677,58 +666,41 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) { -#ifndef Py_UNICODE_WIDE -#define IS_SURROGATE_PAIR(p, end) \ - (*p >= 0xD800 && *p <= 0xDBFF && (p + 1) < end && \ - *(p + 1) >= 0xDC00 && *(p + 1) <= 0xDFFF) -#else -#define IS_SURROGATE_PAIR(p, end) 0 -#endif if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; + Py_ssize_t i; Py_ssize_t start; Py_ssize_t end; PyObject *res; - Py_UNICODE *p; - Py_UNICODE *startp; - Py_UNICODE *outp; + unsigned char *outp; int ressize; + Py_UCS4 c; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; if (PyUnicodeEncodeError_GetEnd(exc, &end)) return NULL; if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; - startp = PyUnicode_AS_UNICODE(object); - for (p = startp+start, ressize = 0; p < startp+end; ++p) { -#ifdef Py_UNICODE_WIDE - if (*p >= 0x00010000) + for (i = start, ressize = 0; i < end; ++i) { + /* object is guaranteed to be "ready" */ + c = PyUnicode_READ_CHAR(object, i); + if (c >= 0x10000) { ressize += 1+1+8; - else -#endif - if (*p >= 0x100) { - if (IS_SURROGATE_PAIR(p, startp+end)) { - ressize += 1+1+8; - ++p; - } - else - ressize += 1+1+4; + } + else if (c >= 0x100) { + ressize += 1+1+4; } else ressize += 1+1+2; } - res = PyUnicode_FromUnicode(NULL, ressize); + res = PyUnicode_New(ressize, 127); if (res==NULL) return NULL; - for (p = startp+start, outp = PyUnicode_AS_UNICODE(res); - p < startp+end; ++p) { - Py_UCS4 c = (Py_UCS4) *p; + for (i = start, outp = PyUnicode_1BYTE_DATA(res); + i < end; ++i) { + c = PyUnicode_READ_CHAR(object, i); *outp++ = '\\'; - if (IS_SURROGATE_PAIR(p, startp+end)) { - c = ((*p & 0x3FF) << 10) + (*(p + 1) & 0x3FF) + 0x10000; - ++p; - } if (c >= 0x00010000) { *outp++ = 'U'; *outp++ = Py_hexdigits[(c>>28)&0xf]; @@ -758,7 +730,6 @@ PyObject *PyCodec_BackslashReplaceErrors(PyObject *exc) wrong_exception_type(exc); return NULL; } -#undef IS_SURROGATE_PAIR } /* This handler is declared static until someone demonstrates @@ -768,12 +739,11 @@ PyCodec_SurrogatePassErrors(PyObject *exc) { PyObject *restuple; PyObject *object; + Py_ssize_t i; Py_ssize_t start; Py_ssize_t end; PyObject *res; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - Py_UNICODE *p; - Py_UNICODE *startp; char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -781,15 +751,15 @@ PyCodec_SurrogatePassErrors(PyObject *exc) return NULL; if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; - startp = PyUnicode_AS_UNICODE(object); res = PyBytes_FromStringAndSize(NULL, 3*(end-start)); if (!res) { Py_DECREF(object); return NULL; } outp = PyBytes_AsString(res); - for (p = startp+start; p < startp+end; p++) { - Py_UNICODE ch = *p; + for (i = start; i < end; i++) { + /* object is guaranteed to be "ready" */ + Py_UCS4 ch = PyUnicode_READ_CHAR(object, i); if (ch < 0xd800 || ch > 0xdfff) { /* Not a surrogate, fail with original exception */ PyErr_SetObject(PyExceptionInstance_Class(exc), exc); @@ -847,12 +817,11 @@ PyCodec_SurrogateEscapeErrors(PyObject *exc) { PyObject *restuple; PyObject *object; + Py_ssize_t i; Py_ssize_t start; Py_ssize_t end; PyObject *res; if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { - Py_UNICODE *p; - Py_UNICODE *startp; char *outp; if (PyUnicodeEncodeError_GetStart(exc, &start)) return NULL; @@ -860,15 +829,15 @@ PyCodec_SurrogateEscapeErrors(PyObject *exc) return NULL; if (!(object = PyUnicodeEncodeError_GetObject(exc))) return NULL; - startp = PyUnicode_AS_UNICODE(object); res = PyBytes_FromStringAndSize(NULL, end-start); if (!res) { Py_DECREF(object); return NULL; } outp = PyBytes_AsString(res); - for (p = startp+start; p < startp+end; p++) { - Py_UNICODE ch = *p; + for (i = start; i < end; i++) { + /* object is guaranteed to be "ready" */ + Py_UCS4 ch = PyUnicode_READ_CHAR(object, i); if (ch < 0xdc80 || ch > 0xdcff) { /* Not a UTF-8b surrogate, fail with original exception */ PyErr_SetObject(PyExceptionInstance_Class(exc), exc); -- cgit v1.2.1 From 762eb600184fb9894e88be2d36aaeecc8d8d5c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 4 Nov 2011 12:26:49 +0100 Subject: Fix C89 incompatibility. --- Python/codecs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 47cdb20add..dcc7c988d6 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -613,9 +613,9 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) outp = PyUnicode_1BYTE_DATA(res); /* generate replacement */ for (i = start, o = 0; i < end; ++i) { - ch = PyUnicode_READ_CHAR(object, i); int digits; int base; + ch = PyUnicode_READ_CHAR(object, i); *outp++ = '&'; *outp++ = '#'; if (ch<10) { -- cgit v1.2.1 From caec74946ceabba5ddd3fa3d57eae053ca2f3767 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 4 Nov 2011 21:29:10 +0100 Subject: PyCodec_XMLCharRefReplaceError(): Remove unused variable --- Python/codecs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index dcc7c988d6..07fe2eee2c 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -573,7 +573,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) if (PyObject_IsInstance(exc, PyExc_UnicodeEncodeError)) { PyObject *restuple; PyObject *object; - Py_ssize_t i, o; + Py_ssize_t i; Py_ssize_t start; Py_ssize_t end; PyObject *res; @@ -612,7 +612,7 @@ PyObject *PyCodec_XMLCharRefReplaceErrors(PyObject *exc) } outp = PyUnicode_1BYTE_DATA(res); /* generate replacement */ - for (i = start, o = 0; i < end; ++i) { + for (i = start; i < end; ++i) { int digits; int base; ch = PyUnicode_READ_CHAR(object, i); -- cgit v1.2.1 From 5e0e358d806886b550069eaa2235d8654ac762db Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 4 Nov 2011 21:36:35 +0100 Subject: Avoid the Py_UNICODE type in codecs.c --- Python/codecs.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index 07fe2eee2c..cdf2c4455a 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -778,7 +778,7 @@ PyCodec_SurrogatePassErrors(PyObject *exc) } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { unsigned char *p; - Py_UNICODE ch = 0; + Py_UCS4 ch = 0; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; if (!(object = PyUnicodeDecodeError_GetObject(exc))) @@ -804,7 +804,10 @@ PyCodec_SurrogatePassErrors(PyObject *exc) PyErr_SetObject(PyExceptionInstance_Class(exc), exc); return NULL; } - return Py_BuildValue("(u#n)", &ch, 1, start+3); + res = PyUnicode_FromOrdinal(ch); + if (res == NULL) + return NULL; + return Py_BuildValue("(Nn)", res, start+3); } else { wrong_exception_type(exc); @@ -853,8 +856,9 @@ PyCodec_SurrogateEscapeErrors(PyObject *exc) return restuple; } else if (PyObject_IsInstance(exc, PyExc_UnicodeDecodeError)) { + PyObject *str; unsigned char *p; - Py_UNICODE ch[4]; /* decode up to 4 bad bytes. */ + Py_UCS2 ch[4]; /* decode up to 4 bad bytes. */ int consumed = 0; if (PyUnicodeDecodeError_GetStart(exc, &start)) return NULL; @@ -879,7 +883,10 @@ PyCodec_SurrogateEscapeErrors(PyObject *exc) PyErr_SetObject(PyExceptionInstance_Class(exc), exc); return NULL; } - return Py_BuildValue("(u#n)", ch, consumed, start+consumed); + str = PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, ch, consumed); + if (str == NULL) + return NULL; + return Py_BuildValue("(Nn)", str, start+consumed); } else { wrong_exception_type(exc); -- cgit v1.2.1 From a8b3fcc7f3a5390f12cab301efda3cef8dadeecf Mon Sep 17 00:00:00 2001 From: Philip Jenvey Date: Sun, 6 Nov 2011 16:37:52 -0800 Subject: quote the type name for improved readability --- 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 4d960b8d1c..871eaa3497 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1121,7 +1121,7 @@ builtin_next(PyObject *self, PyObject *args) return NULL; if (!PyIter_Check(it)) { PyErr_Format(PyExc_TypeError, - "%.200s object is not an iterator", + "'%.200s' object is not an iterator", it->ob_type->tp_name); return NULL; } -- cgit v1.2.1 From 58e1626c76b718d8b7ecd5f847c7102e79a43302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Mon, 7 Nov 2011 13:00:05 +0100 Subject: Make _PyUnicode_FromId return borrowed references. http://mail.python.org/pipermail/python-dev/2011-November/114347.html --- Python/_warnings.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 5846426531..2e5b0dd4e2 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -666,10 +666,8 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) if ((tmp = _PyUnicode_FromId(&PyId_get_source)) == NULL) return NULL; - Py_DECREF(tmp); if ((tmp = _PyUnicode_FromId(&PyId_splitlines)) == NULL) return NULL; - Py_DECREF(tmp); /* Check/get the requisite pieces needed for the loader. */ loader = PyDict_GetItemString(module_globals, "__loader__"); -- cgit v1.2.1 From 17ec0be2a18cb0c8d6dc40f0bf0205642e47c31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Thu, 10 Nov 2011 19:12:29 +0100 Subject: Issue #13303: Fix bytecode file default permission. --- Python/import.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 5c33b6be57..ae1101e4ec 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1202,12 +1202,10 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR | S_IWGRP | S_IWOTH); PyObject *dirbytes; -#endif - int fd; -#ifndef MS_WINDOWS PyObject *cpathbytes, *cpathbytes_tmp; Py_ssize_t cpathbytes_len; #endif + int fd; PyObject *dirname; Py_UCS4 *dirsep; int res, ok; @@ -1275,7 +1273,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, return; } cpathbytes_len = PyBytes_GET_SIZE(cpathbytes); - cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 6); + cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 4); if (cpathbytes_tmp == NULL) { Py_DECREF(cpathbytes); PyErr_Clear(); @@ -1283,9 +1281,10 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } memcpy(PyBytes_AS_STRING(cpathbytes_tmp), PyBytes_AS_STRING(cpathbytes), cpathbytes_len); - memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, "XXXXXX", 6); + memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, ".tmp", 4); - fd = mkstemp(PyBytes_AS_STRING(cpathbytes_tmp)); + fd = open(PyBytes_AS_STRING(cpathbytes_tmp), + O_CREAT | O_EXCL | O_WRONLY, 0666); if (0 <= fd) fp = fdopen(fd, "wb"); else -- cgit v1.2.1 From 1a238237f0304a03e73e464b069a2a4aec4beb3c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 15 Nov 2011 19:15:19 +0100 Subject: Issue #13392: Writing a pyc file should now be atomic under Windows as well. --- Python/import.c | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index ae1101e4ec..3c3e504e28 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1197,6 +1197,8 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, time_t mtime = srcstat->st_mtime; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; + PyObject *cpathname_tmp; + Py_ssize_t cpathname_len; #else mode_t dirmode = (srcstat->st_mode | S_IXUSR | S_IXGRP | S_IXOTH | @@ -1255,18 +1257,29 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } Py_DECREF(dirname); + /* We first write to a tmp file and then take advantage + of atomic renaming (which *should* be true even under Windows). */ #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); + cpathname_len = PyUnicode_GET_LENGTH(cpathname); + cpathname_tmp = PyUnicode_New(cpathname_len + 4, + PyUnicode_MAX_CHAR_VALUE(cpathname)); + if (cpathname_tmp == NULL) { + PyErr_Clear(); + return; + } + PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 0, '.'); + PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 1, 't'); + PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 2, 'm'); + PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 3, 'p'); + (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); + fd = _wopen(PyUnicode_AS_UNICODE(cpathname_tmp), + O_EXCL | O_CREAT | O_WRONLY | O_BINARY, + mode); if (0 <= fd) fp = fdopen(fd, "wb"); else fp = NULL; #else - /* Under POSIX, we first write to a tmp file and then take advantage - of atomic renaming. */ cpathbytes = PyUnicode_EncodeFSDefault(cpathname); if (cpathbytes == NULL) { PyErr_Clear(); @@ -1294,7 +1307,9 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, if (Py_VerboseFlag) PySys_FormatStderr( "# can't create %R\n", cpathname); -#ifndef MS_WINDOWS +#ifdef MS_WINDOWS + Py_DECREF(cpathname_tmp); +#else Py_DECREF(cpathbytes); Py_DECREF(cpathbytes_tmp); #endif @@ -1315,7 +1330,8 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, /* Don't keep partial file */ fclose(fp); #ifdef MS_WINDOWS - (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname)); + (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); + Py_DECREF(cpathname_tmp); #else (void) unlink(PyBytes_AS_STRING(cpathbytes_tmp)); Py_DECREF(cpathbytes); @@ -1324,8 +1340,20 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, return; } fclose(fp); - /* Under POSIX, do an atomic rename */ -#ifndef MS_WINDOWS + /* Do a (hopefully) atomic rename */ +#ifdef MS_WINDOWS + if (!MoveFileExW(PyUnicode_AS_UNICODE(cpathname_tmp), + PyUnicode_AS_UNICODE(cpathname), + MOVEFILE_REPLACE_EXISTING)) { + if (Py_VerboseFlag) + PySys_FormatStderr("# can't write %R\n", cpathname); + /* Don't keep tmp file */ + (void) DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); + Py_DECREF(cpathname_tmp); + return; + } + Py_DECREF(cpathname_tmp); +#else if (rename(PyBytes_AS_STRING(cpathbytes_tmp), PyBytes_AS_STRING(cpathbytes))) { if (Py_VerboseFlag) -- cgit v1.2.1 From 1a11faf52590fae1e61f304835b27c42ed21b1dd Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 15 Nov 2011 20:40:55 +0100 Subject: Fix regression under Windows following b75b41237380 (from issue #13392) --- Python/import.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 3c3e504e28..64197d7a48 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1267,6 +1267,11 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, PyErr_Clear(); return; } + if (PyUnicode_CopyCharacters(cpathname_tmp, 0, + cpathname, 0, cpathname_len) < 0) { + PyErr_Clear(); + return; + } PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 0, '.'); PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 1, 't'); PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 2, 'm'); -- cgit v1.2.1 From 23ad9bf93bf81d89142e55ca1cfb04f9c3ffc837 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 15 Nov 2011 22:27:32 +0100 Subject: Use PyUnicode_FromFormat() to create the temporary file name. Also, as in importlib, append the id of an object to make the file name pseudo-random. --- Python/import.c | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 64197d7a48..b1eca64f4d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1195,17 +1195,15 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, Py_UCS4 *cpathname_ucs4; FILE *fp; time_t mtime = srcstat->st_mtime; + PyObject *cpathname_tmp; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; - PyObject *cpathname_tmp; - Py_ssize_t cpathname_len; #else mode_t dirmode = (srcstat->st_mode | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR | S_IWGRP | S_IWOTH); PyObject *dirbytes; PyObject *cpathbytes, *cpathbytes_tmp; - Py_ssize_t cpathbytes_len; #endif int fd; PyObject *dirname; @@ -1258,24 +1256,18 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, Py_DECREF(dirname); /* We first write to a tmp file and then take advantage - of atomic renaming (which *should* be true even under Windows). */ -#ifdef MS_WINDOWS - cpathname_len = PyUnicode_GET_LENGTH(cpathname); - cpathname_tmp = PyUnicode_New(cpathname_len + 4, - PyUnicode_MAX_CHAR_VALUE(cpathname)); + of atomic renaming (which *should* be true even under Windows). + As in importlib, we use id(something) to generate a pseudo-random + filename. mkstemp() can't be used since it doesn't allow specifying + the file access permissions. + */ + cpathname_tmp = PyUnicode_FromFormat("%U.%zd", + cpathname, (Py_ssize_t) co); if (cpathname_tmp == NULL) { PyErr_Clear(); return; } - if (PyUnicode_CopyCharacters(cpathname_tmp, 0, - cpathname, 0, cpathname_len) < 0) { - PyErr_Clear(); - return; - } - PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 0, '.'); - PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 1, 't'); - PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 2, 'm'); - PyUnicode_WriteChar(cpathname_tmp, cpathname_len + 3, 'p'); +#ifdef MS_WINDOWS (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); fd = _wopen(PyUnicode_AS_UNICODE(cpathname_tmp), O_EXCL | O_CREAT | O_WRONLY | O_BINARY, @@ -1285,22 +1277,17 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, else fp = NULL; #else - cpathbytes = PyUnicode_EncodeFSDefault(cpathname); - if (cpathbytes == NULL) { + cpathbytes_tmp = PyUnicode_EncodeFSDefault(cpathname_tmp); + Py_DECREF(cpathname_tmp); + if (cpathbytes_tmp == NULL) { PyErr_Clear(); return; } - cpathbytes_len = PyBytes_GET_SIZE(cpathbytes); - cpathbytes_tmp = PyBytes_FromStringAndSize(NULL, cpathbytes_len + 4); - if (cpathbytes_tmp == NULL) { - Py_DECREF(cpathbytes); + cpathbytes = PyUnicode_EncodeFSDefault(cpathname); + if (cpathbytes == NULL) { PyErr_Clear(); return; } - memcpy(PyBytes_AS_STRING(cpathbytes_tmp), PyBytes_AS_STRING(cpathbytes), - cpathbytes_len); - memcpy(PyBytes_AS_STRING(cpathbytes_tmp) + cpathbytes_len, ".tmp", 4); - fd = open(PyBytes_AS_STRING(cpathbytes_tmp), O_CREAT | O_EXCL | O_WRONLY, 0666); if (0 <= fd) -- cgit v1.2.1 From 84acdc7c2fbb43c63eab2518445c5a7771755037 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 17 Nov 2011 00:45:54 +0100 Subject: Catch PyUnicode_AS_UNICODE() errors --- Python/import.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index b1eca64f4d..6c6d1f697a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1198,6 +1198,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, PyObject *cpathname_tmp; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; + wchar_t *wdirname, *wpathname, *wpathname_tmp; #else mode_t dirmode = (srcstat->st_mode | S_IXUSR | S_IXGRP | S_IXOTH | @@ -1230,7 +1231,12 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, } #ifdef MS_WINDOWS - res = CreateDirectoryW(PyUnicode_AS_UNICODE(dirname), NULL); + wdirname = PyUnicode_AsUnicode(dirname); + if (wdirname == NULL) { + PyErr_Clear(); + return; + } + res = CreateDirectoryW(wdirname, NULL); ok = (res != 0); if (!ok && GetLastError() == ERROR_ALREADY_EXISTS) ok = 1; @@ -1268,8 +1274,19 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, return; } #ifdef MS_WINDOWS - (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); - fd = _wopen(PyUnicode_AS_UNICODE(cpathname_tmp), + wpathname = PyUnicode_AsUnicode(cpathname); + if (wpathname == NULL) { + PyErr_Clear(); + return; + } + wpathname_tmp = PyUnicode_AsUnicode(cpathname_tmp); + if (wpathname_tmp == NULL) { + PyErr_Clear(); + return; + } + + (void)DeleteFileW(wpathname_tmp); + fd = _wopen(wpathname_tmp, O_EXCL | O_CREAT | O_WRONLY | O_BINARY, mode); if (0 <= fd) @@ -1322,7 +1339,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, /* Don't keep partial file */ fclose(fp); #ifdef MS_WINDOWS - (void)DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); + (void)DeleteFileW(wpathname_tmp); Py_DECREF(cpathname_tmp); #else (void) unlink(PyBytes_AS_STRING(cpathbytes_tmp)); @@ -1334,13 +1351,11 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, fclose(fp); /* Do a (hopefully) atomic rename */ #ifdef MS_WINDOWS - if (!MoveFileExW(PyUnicode_AS_UNICODE(cpathname_tmp), - PyUnicode_AS_UNICODE(cpathname), - MOVEFILE_REPLACE_EXISTING)) { + if (!MoveFileExW(wpathname_tmp, wpathname, MOVEFILE_REPLACE_EXISTING)) { if (Py_VerboseFlag) PySys_FormatStderr("# can't write %R\n", cpathname); /* Don't keep tmp file */ - (void) DeleteFileW(PyUnicode_AS_UNICODE(cpathname_tmp)); + (void) DeleteFileW(wpathname_tmp); Py_DECREF(cpathname_tmp); return; } @@ -1819,10 +1834,10 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, PyUnicode_CopyCharacters(filename, 0, path_unicode, 0, len); pos = len; if (addsep) - PyUnicode_WRITE(PyUnicode_KIND(filename), + PyUnicode_WRITE(PyUnicode_KIND(filename), PyUnicode_DATA(filename), pos++, SEP); - PyUnicode_CopyCharacters(filename, pos, name, 0, + PyUnicode_CopyCharacters(filename, pos, name, 0, PyUnicode_GET_LENGTH(name)); /* Check for package import (buf holds a directory name, @@ -2268,18 +2283,22 @@ case_ok(PyObject *filename, Py_ssize_t prefix_delta, PyObject *name) WIN32_FIND_DATAW data; HANDLE h; int cmp; - wchar_t *wname; + wchar_t *wfilename, *wname; Py_ssize_t wname_len; if (Py_GETENV("PYTHONCASEOK") != NULL) return 1; - h = FindFirstFileW(PyUnicode_AS_UNICODE(filename), &data); + wfilename = PyUnicode_AsUnicode(filename); + if (wfilename == NULL) + return -1; + + h = FindFirstFileW(wfilename, &data); if (h == INVALID_HANDLE_VALUE) { PyErr_Format(PyExc_NameError, "Can't find file for module %R\n(filename %R)", name, filename); - return 0; + return -1; } FindClose(h); @@ -2831,7 +2850,7 @@ import_module_level(PyObject *name, PyObject *globals, PyObject *locals, if (!ensure_fromlist(tail, fromlist, prefix, 0)) goto out; - + result = tail; Py_INCREF(result); out: -- cgit v1.2.1 From 2967d4ef158cca9a434324e6341405857df0123d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 17 Nov 2011 00:51:38 +0100 Subject: Catch PyUnicode_AS_UNICODE() errors in fileutils.c --- Python/fileutils.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index c563eaa5fb..0afa415d59 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -244,8 +244,12 @@ _Py_stat(PyObject *path, struct stat *statbuf) #ifdef MS_WINDOWS int err; struct _stat wstatbuf; + wchar_t *wpath; - err = _wstat(PyUnicode_AS_UNICODE(path), &wstatbuf); + wpath = PyUnicode_AsUnicode(path); + if (wpath == NULL) + return -1; + err = _wstat(wpath, &wstatbuf); if (!err) statbuf->st_mode = wstatbuf.st_mode; return err; @@ -297,14 +301,19 @@ FILE* _Py_fopen(PyObject *path, const char *mode) { #ifdef MS_WINDOWS + wchar_t *wpath; wchar_t wmode[10]; int usize; + wpath = PyUnicode_AsUnicode(path); + if (wpath == NULL) + return NULL; + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); if (usize == 0) return NULL; - return _wfopen(PyUnicode_AS_UNICODE(path), wmode); + return _wfopen(wpath, wmode); #else FILE *f; PyObject *bytes = PyUnicode_EncodeFSDefault(path); -- cgit v1.2.1 From 20c31ce6ca51dcf5219497f8f4bb07110b9144a2 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 18 Nov 2011 20:14:34 +0100 Subject: Issue #10227: Add an allocation cache for a single slice object. Patch by Stefan Behnel. --- Python/pythonrun.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 0f2f0501cd..0c267fc832 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -531,6 +531,7 @@ Py_Finalize(void) PyLong_Fini(); PyFloat_Fini(); PyDict_Fini(); + PySlice_Fini(); /* Cleanup Unicode implementation */ _PyUnicode_Fini(); -- cgit v1.2.1 From fe1c10998b6142e028a7cd63a8f42e5fecb406e0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 20 Nov 2011 19:20:00 +0100 Subject: print_exception() uses PyUnicode_GetLength() instead of PyUnicode_GetSize() --- 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 0c267fc832..389bcd08ec 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1641,7 +1641,7 @@ print_exception(PyObject *f, PyObject *value) if (s == NULL) err = -1; else if (!PyUnicode_Check(s) || - PyUnicode_GetSize(s) != 0) + PyUnicode_GetLength(s) != 0) err = PyFile_WriteString(": ", f); if (err == 0) err = PyFile_WriteObject(s, f, Py_PRINT_RAW); -- cgit v1.2.1 From b2d40d2728272d56781ac9164279d9a3ec900a7c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Nov 2011 02:01:41 +0100 Subject: Check for PyUnicode_AS_UNICODE() failure --- Python/dynload_win.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dynload_win.c b/Python/dynload_win.c index c620e58948..e511098d1d 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -176,11 +176,16 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, { dl_funcptr p; char funcname[258], *import_python; + wchar_t *wpathname; #ifndef _DEBUG _Py_CheckPython3(); #endif + wpathname = PyUnicode_AsUnicode(pathname); + if (wpathname == NULL) + return NULL; + PyOS_snprintf(funcname, sizeof(funcname), "PyInit_%.200s", shortname); { @@ -195,7 +200,7 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, /* 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, + hDLL = LoadLibraryExW(wpathname, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); _Py_DeactivateActCtx(cookie); -- cgit v1.2.1 From ca8cc12c914866d056515be4f028011fd623994c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Nov 2011 02:49:52 +0100 Subject: Fix misuse of PyUnicode_GET_SIZE() => PyUnicode_GET_LENGTH() And PyUnicode_GetSize() => PyUnicode_GetLength() --- Python/_warnings.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 2e5b0dd4e2..a494dd9a3c 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -203,13 +203,13 @@ normalize_module(PyObject *filename) mod_str = _PyUnicode_AsString(filename); if (mod_str == NULL) - return NULL; - len = PyUnicode_GetSize(filename); + return NULL; + len = PyUnicode_GetLength(filename); if (len < 0) return NULL; if (len >= 3 && strncmp(mod_str + (len - 3), ".py", 3) == 0) { - module = PyUnicode_FromStringAndSize(mod_str, len-3); + module = PyUnicode_Substring(filename, 0, len-3); } else { module = filename; @@ -506,7 +506,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, if (PyUnicode_READY(*filename)) goto handle_error; - len = PyUnicode_GetSize(*filename); + len = PyUnicode_GetLength(*filename); kind = PyUnicode_KIND(*filename); data = PyUnicode_DATA(*filename); @@ -690,7 +690,7 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) } /* Split the source into lines. */ - source_list = PyObject_CallMethodObjArgs(source, + source_list = PyObject_CallMethodObjArgs(source, PyId_splitlines.object, NULL); Py_DECREF(source); -- cgit v1.2.1 From 05407577effc3f36d9b63c12b8e754eb86e8e3f6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Nov 2011 02:27:30 +0100 Subject: Use the new Unicode API * Replace PyUnicode_FromUnicode(NULL, 0) by PyUnicode_New(0, 0) * Replce PyUnicode_FromUnicode(str, len) by PyUnicode_FromWideChar(str, len) * Replace Py_UNICODE by wchar_t * posix_putenv() uses PyUnicode_FromFormat() to create the string, instead of PyUnicode_FromUnicode() + _snwprintf() --- Python/dynload_win.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/dynload_win.c b/Python/dynload_win.c index e511098d1d..2cbfe9f30d 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -249,7 +249,7 @@ dl_funcptr _PyImport_GetDynLoadWindows(const char *shortname, "DLL load failed: "); PyUnicode_AppendAndDel(&message, - PyUnicode_FromUnicode( + PyUnicode_FromWideChar( theInfo, theLength)); } -- cgit v1.2.1 From 806c2672ae49f639fd7a8a14a9a8ce67a14e94a6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Nov 2011 03:31:20 +0100 Subject: Remove "#ifdef Py_UNICODE_WIDE": Python is now always wide --- Python/bltinmodule.c | 11 ++--------- Python/traceback.c | 10 ++-------- 2 files changed, 4 insertions(+), 17 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 871eaa3497..13349cc7bb 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -518,17 +518,10 @@ builtin_chr(PyObject *self, PyObject *args) return PyUnicode_FromOrdinal(x); } -PyDoc_VAR(chr_doc) = PyDoc_STR( +PyDoc_STRVAR(chr_doc, "chr(i) -> Unicode character\n\ \n\ -Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff." -) -#ifndef Py_UNICODE_WIDE -PyDoc_STR( -"\nIf 0x10000 <= i, a surrogate pair is returned." -) -#endif -; +Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); static char * diff --git a/Python/traceback.c b/Python/traceback.c index 2f4653bce6..c8b3ee1b63 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -526,23 +526,17 @@ dump_ascii(int fd, PyObject *text) char c = (char)ch; write(fd, &c, 1); } - else if (ch < 256) { + else if (ch < 0xff) { PUTS(fd, "\\x"); dump_hexadecimal(2, ch, fd); } - else -#ifdef Py_UNICODE_WIDE - if (ch < 65536) -#endif - { + else if (ch < 0xffff) { PUTS(fd, "\\u"); dump_hexadecimal(4, ch, fd); -#ifdef Py_UNICODE_WIDE } else { PUTS(fd, "\\U"); dump_hexadecimal(8, ch, fd); -#endif } } if (truncated) -- cgit v1.2.1 From 949c3f094c436fea35325980527d63d0d9eabd21 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 25 Nov 2011 18:56:07 +0100 Subject: PEP 3155 / issue #13448: Qualified name for classes and functions. --- Python/ceval.c | 4 +- Python/compile.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++-------- Python/import.c | 3 +- 3 files changed, 125 insertions(+), 21 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 8d980fdc93..ed82b9411a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2687,9 +2687,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) int kwdefaults = (oparg>>8) & 0xff; int num_annotations = (oparg >> 16) & 0x7fff; + w = POP(); /* qualname */ v = POP(); /* code object */ - x = PyFunction_New(v, f->f_globals); + x = PyFunction_NewWithQualName(v, f->f_globals, w); Py_DECREF(v); + Py_DECREF(w); if (x != NULL && opcode == MAKE_CLOSURE) { v = POP(); diff --git a/Python/compile.c b/Python/compile.c index 906772289d..849f48785d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -90,6 +90,13 @@ struct fblockinfo { basicblock *fb_block; }; +enum { + COMPILER_SCOPE_MODULE, + COMPILER_SCOPE_CLASS, + COMPILER_SCOPE_FUNCTION, + COMPILER_SCOPE_COMPREHENSION, +}; + /* The following items change on entry and exit of code blocks. They must be saved and restored when returning to a block. */ @@ -97,6 +104,9 @@ struct compiler_unit { PySTEntryObject *u_ste; PyObject *u_name; + PyObject *u_qualname; /* dot-separated qualified name (lazy) */ + int u_scope_type; + /* The following fields are dicts that map objects to the index of them in co_XXX. The index is used as the argument for opcodes that refer to those collections. @@ -149,7 +159,7 @@ struct compiler { PyArena *c_arena; /* pointer to memory allocation arena */ }; -static int compiler_enter_scope(struct compiler *, identifier, void *, int); +static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); static int compiler_next_instr(struct compiler *, basicblock *); @@ -457,6 +467,7 @@ compiler_unit_free(struct compiler_unit *u) } Py_CLEAR(u->u_ste); Py_CLEAR(u->u_name); + Py_CLEAR(u->u_qualname); Py_CLEAR(u->u_consts); Py_CLEAR(u->u_names); Py_CLEAR(u->u_varnames); @@ -467,8 +478,8 @@ compiler_unit_free(struct compiler_unit *u) } static int -compiler_enter_scope(struct compiler *c, identifier name, void *key, - int lineno) +compiler_enter_scope(struct compiler *c, identifier name, + int scope_type, void *key, int lineno) { struct compiler_unit *u; @@ -479,6 +490,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, return 0; } memset(u, 0, sizeof(struct compiler_unit)); + u->u_scope_type = scope_type; u->u_argcount = 0; u->u_kwonlyargcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); @@ -566,6 +578,59 @@ compiler_exit_scope(struct compiler *c) } +static PyObject * +compiler_scope_qualname(struct compiler *c) +{ + Py_ssize_t stack_size, i; + _Py_static_string(dot, "."); + _Py_static_string(locals, ""); + struct compiler_unit *u; + PyObject *capsule, *name, *seq, *dot_str, *locals_str; + + u = c->u; + if (u->u_qualname != NULL) { + Py_INCREF(u->u_qualname); + return u->u_qualname; + } + + seq = PyList_New(0); + if (seq == NULL) + return NULL; + + stack_size = PyList_GET_SIZE(c->c_stack); + for (i = 0; i < stack_size; i++) { + capsule = PyList_GET_ITEM(c->c_stack, i); + u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + assert(u); + if (u->u_scope_type == COMPILER_SCOPE_MODULE) + continue; + if (PyList_Append(seq, u->u_name)) + goto _error; + if (u->u_scope_type == COMPILER_SCOPE_FUNCTION) { + locals_str = _PyUnicode_FromId(&locals); + if (locals_str == NULL) + goto _error; + if (PyList_Append(seq, locals_str)) + goto _error; + } + } + u = c->u; + if (PyList_Append(seq, u->u_name)) + goto _error; + dot_str = _PyUnicode_FromId(&dot); + if (dot_str == NULL) + goto _error; + name = PyUnicode_Join(dot_str, seq); + Py_DECREF(seq); + u->u_qualname = name; + Py_XINCREF(name); + return name; + +_error: + Py_XDECREF(seq); + return NULL; +} + /* Allocate a new block and return a pointer to it. Returns NULL on error. */ @@ -862,9 +927,9 @@ opcode_stack_effect(int opcode, int oparg) case CALL_FUNCTION_VAR_KW: return -NARGS(oparg)-2; case MAKE_FUNCTION: - return -NARGS(oparg) - ((oparg >> 16) & 0xffff); + return -1 -NARGS(oparg) - ((oparg >> 16) & 0xffff); case MAKE_CLOSURE: - return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff); + return -2 - NARGS(oparg) - ((oparg >> 16) & 0xffff); #undef NARGS case BUILD_SLICE: if (oparg == 3) @@ -1194,7 +1259,7 @@ compiler_mod(struct compiler *c, mod_ty mod) return NULL; } /* Use 0 for firstlineno initially, will fixup in assemble(). */ - if (!compiler_enter_scope(c, module, mod, 0)) + if (!compiler_enter_scope(c, module, COMPILER_SCOPE_MODULE, mod, 0)) return NULL; switch (mod->kind) { case Module_kind: @@ -1270,11 +1335,15 @@ compiler_lookup_arg(PyObject *dict, PyObject *name) } static int -compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) +compiler_make_closure(struct compiler *c, PyCodeObject *co, int args, PyObject *qualname) { int i, free = PyCode_GetNumFree(co); + if (qualname == NULL) + qualname = co->co_name; + if (free == 0) { ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); + ADDOP_O(c, LOAD_CONST, qualname, consts); ADDOP_I(c, MAKE_FUNCTION, args); return 1; } @@ -1311,6 +1380,7 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) } ADDOP_I(c, BUILD_TUPLE, free); ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); + ADDOP_O(c, LOAD_CONST, qualname, consts); ADDOP_I(c, MAKE_CLOSURE, args); return 1; } @@ -1452,7 +1522,7 @@ static int compiler_function(struct compiler *c, stmt_ty s) { PyCodeObject *co; - PyObject *first_const = Py_None; + PyObject *qualname, *first_const = Py_None; arguments_ty args = s->v.FunctionDef.args; expr_ty returns = s->v.FunctionDef.returns; asdl_seq* decos = s->v.FunctionDef.decorator_list; @@ -1478,7 +1548,8 @@ compiler_function(struct compiler *c, stmt_ty s) return 0; assert((num_annotations & 0xFFFF) == num_annotations); - if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, + if (!compiler_enter_scope(c, s->v.FunctionDef.name, + COMPILER_SCOPE_FUNCTION, (void *)s, s->lineno)) return 0; @@ -1500,14 +1571,19 @@ compiler_function(struct compiler *c, stmt_ty s) VISIT_IN_SCOPE(c, stmt, st); } co = assemble(c, 1); + qualname = compiler_scope_qualname(c); compiler_exit_scope(c); - if (co == NULL) + if (qualname == NULL || co == NULL) { + Py_XDECREF(qualname); + Py_XDECREF(co); return 0; + } arglength = asdl_seq_LEN(args->defaults); arglength |= kw_default_count << 8; arglength |= num_annotations << 16; - compiler_make_closure(c, co, arglength); + compiler_make_closure(c, co, arglength, qualname); + Py_DECREF(qualname); Py_DECREF(co); /* decorators */ @@ -1542,7 +1618,8 @@ compiler_class(struct compiler *c, stmt_ty s) */ /* 1. compile the class body into a code object */ - if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) + if (!compiler_enter_scope(c, s->v.ClassDef.name, + COMPILER_SCOPE_CLASS, (void *)s, s->lineno)) return 0; /* this block represents what we do in the new scope */ { @@ -1572,6 +1649,21 @@ compiler_class(struct compiler *c, stmt_ty s) return 0; } Py_DECREF(str); + /* store the __qualname__ */ + str = compiler_scope_qualname(c); + if (!str) { + compiler_exit_scope(c); + return 0; + } + ADDOP_O(c, LOAD_CONST, str, consts); + Py_DECREF(str); + str = PyUnicode_InternFromString("__qualname__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); /* compile the body proper */ if (!compiler_body(c, s->v.ClassDef.body)) { compiler_exit_scope(c); @@ -1608,7 +1700,7 @@ compiler_class(struct compiler *c, stmt_ty s) ADDOP(c, LOAD_BUILD_CLASS); /* 3. load a function (or closure) made from the code object */ - compiler_make_closure(c, co, 0); + compiler_make_closure(c, co, 0, NULL); Py_DECREF(co); /* 4. load class name */ @@ -1659,6 +1751,7 @@ static int compiler_lambda(struct compiler *c, expr_ty e) { PyCodeObject *co; + PyObject *qualname; static identifier name; int kw_default_count = 0, arglength; arguments_ty args = e->v.Lambda.args; @@ -1678,7 +1771,8 @@ compiler_lambda(struct compiler *c, expr_ty e) } if (args->defaults) VISIT_SEQ(c, expr, args->defaults); - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) + if (!compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, + (void *)e, e->lineno)) return 0; /* Make None the first constant, so the lambda can't have a @@ -1696,13 +1790,15 @@ compiler_lambda(struct compiler *c, expr_ty e) ADDOP_IN_SCOPE(c, RETURN_VALUE); } co = assemble(c, 1); + qualname = compiler_scope_qualname(c); compiler_exit_scope(c); - if (co == NULL) + if (qualname == NULL || co == NULL) return 0; arglength = asdl_seq_LEN(args->defaults); arglength |= kw_default_count << 8; - compiler_make_closure(c, co, arglength); + compiler_make_closure(c, co, arglength, qualname); + Py_DECREF(qualname); Py_DECREF(co); return 1; @@ -2916,11 +3012,13 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, { PyCodeObject *co = NULL; expr_ty outermost_iter; + PyObject *qualname = NULL; outermost_iter = ((comprehension_ty) asdl_seq_GET(generators, 0))->iter; - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) + if (!compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION, + (void *)e, e->lineno)) goto error; if (type != COMP_GENEXP) { @@ -2953,12 +3051,14 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, } co = assemble(c, 1); + qualname = compiler_scope_qualname(c); compiler_exit_scope(c); - if (co == NULL) + if (qualname == NULL || co == NULL) goto error; - if (!compiler_make_closure(c, co, 0)) + if (!compiler_make_closure(c, co, 0, qualname)) goto error; + Py_DECREF(qualname); Py_DECREF(co); VISIT(c, expr, outermost_iter); @@ -2968,6 +3068,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, error_in_scope: compiler_exit_scope(c); error: + Py_XDECREF(qualname); Py_XDECREF(co); return 0; } diff --git a/Python/import.c b/Python/import.c index 6c6d1f697a..7199230098 100644 --- a/Python/import.c +++ b/Python/import.c @@ -103,6 +103,7 @@ typedef unsigned short mode_t; tag: cpython-32 Python 3.2a2 3180 (add DELETE_DEREF) Python 3.3a0 3190 __class__ super closure changed + Python 3.3a0 3200 (__qualname__ added) */ /* MAGIC must change whenever the bytecode emitted by the compiler may no @@ -115,7 +116,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 (3190 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3200 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" /* Current magic word and string tag as globals. */ -- cgit v1.2.1 From ba2c39f9d3821cb88b0ebab7bb40fa48405e78a5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 1 Dec 2011 02:52:11 +0100 Subject: PyCodec_IgnoreErrors() avoids the deprecated "u#" format --- Python/codecs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/codecs.c b/Python/codecs.c index cdf2c4455a..9b0c4b2f44 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -510,8 +510,7 @@ PyObject *PyCodec_IgnoreErrors(PyObject *exc) wrong_exception_type(exc); return NULL; } - /* ouch: passing NULL, 0, pos gives None instead of u'' */ - return Py_BuildValue("(u#n)", &end, 0, end); + return Py_BuildValue("(Nn)", PyUnicode_New(0, 0), end); } -- cgit v1.2.1 From c2a7e9ed61166d07969bf0553753b86430ef6943 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 1 Dec 2011 15:27:04 +0000 Subject: Issue #9530: Fix undefined behaviour due to signed overflow in Python/formatter_unicode.c. --- Python/formatter_unicode.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index fda79fc657..6deb3cd7fe 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -51,7 +51,7 @@ static int get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end, Py_ssize_t *result) { - Py_ssize_t accumulator, digitval, oldaccumulator; + Py_ssize_t accumulator, digitval; int numdigits; accumulator = numdigits = 0; for (;;(*pos)++, numdigits++) { @@ -61,19 +61,17 @@ get_integer(PyObject *str, Py_ssize_t *pos, Py_ssize_t end, if (digitval < 0) break; /* - This trick was copied from old Unicode format code. It's cute, - but would really suck on an old machine with a slow divide - implementation. Fortunately, in the normal case we do not - expect too many digits. + Detect possible overflow before it happens: + + accumulator * 10 + digitval > PY_SSIZE_T_MAX if and only if + accumulator > (PY_SSIZE_T_MAX - digitval) / 10. */ - oldaccumulator = accumulator; - accumulator *= 10; - if ((accumulator+10)/10 != oldaccumulator+1) { + if (accumulator > (PY_SSIZE_T_MAX - digitval) / 10) { PyErr_Format(PyExc_ValueError, "Too many decimal digits in format string"); return -1; } - accumulator += digitval; + accumulator = accumulator * 10 + digitval; } *result = accumulator; return numdigits; -- cgit v1.2.1 From 07c717edd69dd5e05901335996d83fe11d6a24e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Wed, 7 Dec 2011 19:16:01 +0100 Subject: Issue #11051: Reduce the number of syscalls per import. --- Python/import.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 7199230098..9773687f62 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1944,8 +1944,7 @@ find_module_path_list(PyObject *fullname, PyObject *name, if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %R\n", filename); - if (_Py_stat(filename, &statbuf) == 0 && /* it exists */ - S_ISDIR(statbuf.st_mode)) /* it's a directory */ + if (_Py_stat(filename, &statbuf) != 0 || S_ISDIR(statbuf.st_mode)) { Py_DECREF(filename); continue; -- cgit v1.2.1 From d07179846c02fb4a745fd29f7ddfcfc8f51e366b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Wed, 7 Dec 2011 23:17:58 +0100 Subject: Followup to a541bda2f5e2: Add a short comment. --- Python/import.c | 1 + 1 file changed, 1 insertion(+) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index 9773687f62..47839c543d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1946,6 +1946,7 @@ find_module_path_list(PyObject *fullname, PyObject *name, if (_Py_stat(filename, &statbuf) != 0 || S_ISDIR(statbuf.st_mode)) { + /* it doesn't exist, or it's a directory */ Py_DECREF(filename); continue; } -- cgit v1.2.1 From b15cf649f348f5af9bd8f38405377c5be866a6d8 Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Mon, 12 Dec 2011 18:54:29 +0100 Subject: Issue #13575: there is only one class type. --- Python/errors.c | 2 +- Python/pythonrun.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index cd0f68dff4..36b8c545ac 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -665,7 +665,7 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict) if (bases == NULL) goto failure; } - /* Create a real new-style class. */ + /* Create a real class. */ result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO", dot+1, bases, dict); failure: diff --git a/Python/pythonrun.c b/Python/pythonrun.c index abc9ffc994..c8d1e90074 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -474,7 +474,7 @@ Py_Finalize(void) flush_std_files(); /* Collect final garbage. This disposes of cycles created by - * new-style class definitions, for example. + * class definitions, for example. * XXX This is disabled because it caused too many problems. If * XXX a __del__ or weakref callback triggers here, Python code has * XXX a hard time running, because even the sys module has been @@ -1348,11 +1348,6 @@ parse_syntax_error(PyObject *err, PyObject **message, const char **filename, _Py_IDENTIFIER(offset); _Py_IDENTIFIER(text); - /* old style errors */ - if (PyTuple_Check(err)) - return PyArg_ParseTuple(err, "O(ziiz)", message, filename, - lineno, offset, text); - /* new style errors. `err' is an instance */ if (! (v = _PyObject_GetAttrId(err, &PyId_msg))) -- cgit v1.2.1 From ab895ebc75ae51642db6392c58a0f7addb2c96cf Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 16 Dec 2011 23:56:01 +0100 Subject: Add PyUnicode_DecodeLocaleAndSize() and PyUnicode_DecodeLocale() * PyUnicode_DecodeLocaleAndSize() and PyUnicode_DecodeLocale() decode a string from the current locale encoding * _Py_char2wchar() writes an "error code" in the size argument to indicate if the function failed because of memory allocation failure or because of a decoding error. The function doesn't write the error message directly to stderr. * Fix time.strftime() (if wcsftime() is missing): decode strftime() result from the current locale encoding, not from the filesystem encoding. --- Python/fileutils.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 0afa415d59..0aad2200fb 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -16,7 +16,9 @@ Return a pointer to a newly allocated wide character string (use PyMem_Free() to free the memory) and write the number of written wide characters excluding the null character into *size if size is not NULL, or - NULL on error (conversion or memory allocation error). + NULL on error (decoding or memory allocation error). If size is not NULL, + *size is set to (size_t)-1 on memory error and (size_t)-2 on decoding + error. Conversion errors should never happen, unless there is a bug in the C library. */ @@ -82,8 +84,9 @@ _Py_char2wchar(const char* arg, size_t *size) since we provide everything that we have - unless there is a bug in the C library, or I misunderstood how mbrtowc works. */ - fprintf(stderr, "unexpected mbrtowc result -2\n"); PyMem_Free(res); + if (size != NULL) + *size = (size_t)-2; return NULL; } if (converted == (size_t)-1) { @@ -112,7 +115,8 @@ _Py_char2wchar(const char* arg, size_t *size) is ASCII (i.e. escape all bytes > 128. This will still roundtrip correctly in the locale's charset, which must be an ASCII superset. */ res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t)); - if (!res) goto oom; + if (!res) + goto oom; in = (unsigned char*)arg; out = res; while(*in) @@ -126,7 +130,8 @@ _Py_char2wchar(const char* arg, size_t *size) *size = out - res; return res; oom: - fprintf(stderr, "out of memory\n"); + if (size != NULL) + *size = (size_t)-1; return NULL; } @@ -137,10 +142,10 @@ oom: This function is the reverse of _Py_char2wchar(). Return a pointer to a newly allocated byte string (use PyMem_Free() to free - the memory), or NULL on conversion or memory allocation error. + the memory), or NULL on encoding or memory allocation error. If error_pos is not NULL: *error_pos is the index of the invalid character - on conversion error, or (size_t)-1 otherwise. */ + on encoding error, or (size_t)-1 otherwise. */ char* _Py_wchar2char(const wchar_t *text, size_t *error_pos) { @@ -328,7 +333,7 @@ _Py_fopen(PyObject *path, const char *mode) #ifdef HAVE_READLINK /* Read value of symbolic link. Encode the path to the locale encoding, decode - the result from the locale encoding. */ + the result from the locale encoding. Return -1 on error. */ int _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) @@ -372,7 +377,8 @@ _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz) #ifdef HAVE_REALPATH /* Return the canonicalized absolute pathname. Encode path to the locale - encoding, decode the result from the locale encoding. */ + encoding, decode the result from the locale encoding. + Return NULL on error. */ wchar_t* _Py_wrealpath(const wchar_t *path, @@ -410,7 +416,8 @@ _Py_wrealpath(const wchar_t *path, #endif /* Get the current directory. size is the buffer size in wide characters - including the null character. Decode the path from the locale encoding. */ + including the null character. Decode the path from the locale encoding. + Return NULL on error. */ wchar_t* _Py_wgetcwd(wchar_t *buf, size_t size) -- cgit v1.2.1 From 6e12c9c2963cfe7327fcdf99f151c05f5cdaf240 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 17 Dec 2011 04:45:09 +0100 Subject: Issue #13560: os.strerror() now uses the current locale encoding instead of UTF-8 --- Python/errors.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 36b8c545ac..122e444b82 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -343,9 +343,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) PyObject *message; PyObject *v, *args; int i = errno; -#ifndef MS_WINDOWS - char *s; -#else +#ifdef MS_WINDOWS WCHAR *s_buf = NULL; #endif /* Unix/Windows */ @@ -355,11 +353,14 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) #endif #ifndef MS_WINDOWS - if (i == 0) - s = "Error"; /* Sometimes errno didn't get set */ - else - s = strerror(i); - message = PyUnicode_DecodeUTF8(s, strlen(s), "ignore"); + if (i != 0) { + char *s = strerror(i); + message = PyUnicode_DecodeLocale(s, 1); + } + else { + /* Sometimes errno didn't get set */ + message = PyUnicode_FromString("Error"); + } #else if (i == 0) message = PyUnicode_FromString("Error"); /* Sometimes errno didn't get set */ -- cgit v1.2.1 From d7170a94c2cd4e21a5c81fb30344839b63bbe313 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 17 Dec 2011 05:47:23 +0100 Subject: Issue #13560: Locale codec functions use the classic "errors" parameter, instead of surrogateescape So it would be possible to support more error handlers later. --- Python/errors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 122e444b82..31fa9e2955 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -355,7 +355,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) #ifndef MS_WINDOWS if (i != 0) { char *s = strerror(i); - message = PyUnicode_DecodeLocale(s, 1); + message = PyUnicode_DecodeLocale(s, "surrogateescape"); } else { /* Sometimes errno didn't get set */ -- cgit v1.2.1 From 219d85b51cf4eed90b0cd74706d6b55b3753c604 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 18 Dec 2011 20:47:30 +0100 Subject: import.c now catchs _Py_stat() exceptions _Py_stat() now returns -2 if an exception was raised. --- Python/fileutils.c | 8 ++++---- Python/import.c | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 11 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 0aad2200fb..8c049e02af 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -240,8 +240,8 @@ _Py_wstat(const wchar_t* path, struct stat *buf) /* Call _wstat() on Windows, or encode the path to the filesystem encoding and call stat() otherwise. Only fill st_mode attribute on Windows. - Return 0 on success, -1 on _wstat() / stat() error or (if PyErr_Occurred()) - unicode error. */ + Return 0 on success, -1 on _wstat() / stat() error, -2 if an exception was + raised. */ int _Py_stat(PyObject *path, struct stat *statbuf) @@ -253,7 +253,7 @@ _Py_stat(PyObject *path, struct stat *statbuf) wpath = PyUnicode_AsUnicode(path); if (wpath == NULL) - return -1; + return -2; err = _wstat(wpath, &wstatbuf); if (!err) statbuf->st_mode = wstatbuf.st_mode; @@ -262,7 +262,7 @@ _Py_stat(PyObject *path, struct stat *statbuf) int ret; PyObject *bytes = PyUnicode_EncodeFSDefault(path); if (bytes == NULL) - return -1; + return -2; ret = stat(PyBytes_AS_STRING(bytes), statbuf); Py_DECREF(bytes); return ret; diff --git a/Python/import.c b/Python/import.c index 47839c543d..34d1a26dc7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1527,6 +1527,7 @@ get_sourcefile(PyObject *filename) Py_UCS4 *fileuni; PyObject *py; struct stat statbuf; + int err; len = PyUnicode_GET_LENGTH(filename); if (len == 0) @@ -1554,7 +1555,10 @@ get_sourcefile(PyObject *filename) if (py == NULL) goto error; - if (_Py_stat(py, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + err = _Py_stat(py, &statbuf); + if (err == -2) + goto error; + if (err == 0 && S_ISREG(statbuf.st_mode)) { PyMem_Free(fileuni); return py; } @@ -1760,7 +1764,7 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, Py_ssize_t len, pos; struct stat statbuf; static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; - int result, addsep; + int err, result, addsep; if (PyUnicode_Check(path)) { Py_INCREF(path); @@ -1844,7 +1848,12 @@ find_module_path(PyObject *fullname, PyObject *name, PyObject *path, /* Check for package import (buf holds a directory name, and there's an __init__ module in that directory */ #ifdef HAVE_STAT - if (_Py_stat(filename, &statbuf) == 0 && /* it exists */ + err = _Py_stat(filename, &statbuf); + if (err == -2) { + result = -1; + goto out; + } + if (err == 0 && /* it exists */ S_ISDIR(statbuf.st_mode)) /* it's a directory */ { int match; @@ -1905,6 +1914,7 @@ find_module_path_list(PyObject *fullname, PyObject *name, FILE *fp = NULL; PyObject *prefix, *filename; int match; + int err; npath = PyList_Size(search_path_list); for (i = 0; i < npath; i++) { @@ -1944,8 +1954,13 @@ find_module_path_list(PyObject *fullname, PyObject *name, if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %R\n", filename); - if (_Py_stat(filename, &statbuf) != 0 || S_ISDIR(statbuf.st_mode)) - { + err = _Py_stat(filename, &statbuf); + if (err == -2) { + Py_DECREF(prefix); + Py_DECREF(filename); + return NULL; + } + if (err != 0 || S_ISDIR(statbuf.st_mode)) { /* it doesn't exist, or it's a directory */ Py_DECREF(filename); continue; @@ -2345,11 +2360,15 @@ find_init_module(PyObject *directory) struct stat statbuf; PyObject *filename; int match; + int err; filename = PyUnicode_FromFormat("%U%c__init__.py", directory, SEP); if (filename == NULL) return -1; - if (_Py_stat(filename, &statbuf) == 0) { + err = _Py_stat(filename, &statbuf); + if (err == -2) + return -1; + if (err == 0) { /* 3=len(".py") */ match = case_ok(filename, -3, initstr); if (match < 0) { @@ -2367,7 +2386,12 @@ find_init_module(PyObject *directory) directory, SEP, Py_OptimizeFlag ? 'o' : 'c'); if (filename == NULL) return -1; - if (_Py_stat(filename, &statbuf) == 0) { + err = _Py_stat(filename, &statbuf); + if (err == -2) { + Py_DECREF(filename); + return -1; + } + if (err == 0) { /* 4=len(".pyc") */ match = case_ok(filename, -4, initstr); if (match < 0) { -- cgit v1.2.1 From 65f4c8fb8a67c300410ad2835b7850a2bedef51c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 19 Dec 2011 18:19:06 +0100 Subject: _Py_fopen now allows bytes filenames under non-Windows platforms. --- Python/fileutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 8c049e02af..1e71431c00 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -321,8 +321,8 @@ _Py_fopen(PyObject *path, const char *mode) return _wfopen(wpath, wmode); #else FILE *f; - PyObject *bytes = PyUnicode_EncodeFSDefault(path); - if (bytes == NULL) + PyObject *bytes; + if (!PyUnicode_FSConverter(path, &bytes)) return NULL; f = fopen(PyBytes_AS_STRING(bytes), mode); Py_DECREF(bytes); -- cgit v1.2.1 From 5b02c29edfe71ff031b4bfa5e07063018d552f11 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 22 Dec 2011 10:03:38 +0100 Subject: Issue #13626: Add support for SSL Diffie-Hellman key exchange, through the SSLContext.load_dh_params() method and the ssl.OP_SINGLE_DH_USE option. --- Python/fileutils.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 1e71431c00..8993c8c497 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -310,6 +310,12 @@ _Py_fopen(PyObject *path, const char *mode) wchar_t wmode[10]; int usize; + if (!PyUnicode_Check(path)) { + PyErr_Format(PyExc_TypeError, + "str file path expected under Windows, got %R", + Py_TYPE(path)); + return NULL; + } wpath = PyUnicode_AsUnicode(path); if (wpath == NULL) return NULL; -- cgit v1.2.1 From 6ebaf24a65c493bffaccd39bacf38b12e4604fec Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 4 Jan 2012 00:33:50 +0100 Subject: Add a new PyUnicode_Fill() function It is faster than the unicode_fill() function which was implemented in formatter_unicode.c. --- Python/formatter_unicode.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 6deb3cd7fe..ef0151192b 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -317,15 +317,6 @@ calc_padding(Py_ssize_t nchars, Py_ssize_t width, Py_UCS4 align, *n_rpadding = *n_total - nchars - *n_lpadding; } -static void -unicode_fill(PyObject *str, Py_ssize_t start, Py_ssize_t end, Py_UCS4 ch) -{ - int kind = PyUnicode_KIND(str); - void *data = PyUnicode_DATA(str); - while (start < end) - PyUnicode_WRITE(kind, data, start++, ch); -} - /* Do the padding, and return a pointer to where the caller-supplied content goes. */ static Py_ssize_t @@ -335,12 +326,12 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars, { /* Pad on left. */ if (n_lpadding) - unicode_fill(s, start, start + n_lpadding, fill_char); + PyUnicode_Fill(s, start, start + n_lpadding, fill_char); /* Pad on right. */ if (n_rpadding) - unicode_fill(s, start + nchars + n_lpadding, - start + nchars + n_lpadding + n_rpadding, fill_char); + PyUnicode_Fill(s, start + nchars + n_lpadding, + start + nchars + n_lpadding + n_rpadding, fill_char); /* Pointer to the user content. */ return start + n_lpadding; @@ -557,7 +548,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, #endif if (spec->n_lpadding) { - unicode_fill(out, pos, pos + spec->n_lpadding, fill_char); + PyUnicode_Fill(out, pos, pos + spec->n_lpadding, fill_char); pos += spec->n_lpadding; } if (spec->n_sign == 1) { @@ -581,7 +572,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, pos += spec->n_prefix; } if (spec->n_spadding) { - unicode_fill(out, pos, pos + spec->n_spadding, fill_char); + PyUnicode_Fill(out, pos, pos + spec->n_spadding, fill_char); pos += spec->n_spadding; } @@ -640,7 +631,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, } if (spec->n_rpadding) { - unicode_fill(out, pos, pos + spec->n_rpadding, fill_char); + PyUnicode_Fill(out, pos, pos + spec->n_rpadding, fill_char); pos += spec->n_rpadding; } return 0; -- cgit v1.2.1 From 0d2f16a616919bf255b1b100e18347381b39a928 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 11 Jan 2012 21:00:42 -0500 Subject: remove some usage of Py_UNICODE_TOUPPER/LOWER --- Python/_warnings.c | 9 +++++---- Python/formatter_unicode.c | 27 ++++++++++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index 458e346aa3..adebd51ed2 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -510,13 +510,14 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, kind = PyUnicode_KIND(*filename); data = PyUnicode_DATA(*filename); +#define ascii_lower(c) ((c <= 127) ? Py_TOLOWER(c) : 0) /* if filename.lower().endswith((".pyc", ".pyo")): */ if (len >= 4 && PyUnicode_READ(kind, data, len-4) == '.' && - Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-3)) == 'p' && - Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-2)) == 'y' && - (Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'c' || - Py_UNICODE_TOLOWER(PyUnicode_READ(kind, data, len-1)) == 'o')) + ascii_lower(PyUnicode_READ(kind, data, len-3)) == 'p' && + ascii_lower(PyUnicode_READ(kind, data, len-2)) == 'y' && + (ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'c' || + ascii_lower(PyUnicode_READ(kind, data, len-1)) == 'o')) { *filename = PyUnicode_Substring(*filename, 0, PyUnicode_GET_LENGTH(*filename)-1); diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index ef0151192b..12b880d7e7 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -561,13 +561,14 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, return -1; if (toupper) { Py_ssize_t t; - /* XXX if the upper-case prefix is wider than the target - buffer, the caller should have allocated a wider string, - but currently doesn't. */ - for (t = 0; t < spec->n_prefix; ++t) - PyUnicode_WRITE(kind, data, pos + t, - Py_UNICODE_TOUPPER( - PyUnicode_READ(kind, data, pos + t))); + for (t = 0; t < spec->n_prefix; t++) { + Py_UCS4 c = PyUnicode_READ(kind, data, pos + t); + if (c > 127) { + PyErr_SetString(PyExc_SystemError, "prefix not ASCII"); + return -1; + } + PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c)); + } } pos += spec->n_prefix; } @@ -607,10 +608,14 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, } if (toupper) { Py_ssize_t t; - for (t = 0; t < spec->n_grouped_digits; ++t) - PyUnicode_WRITE(kind, data, pos + t, - Py_UNICODE_TOUPPER( - PyUnicode_READ(kind, data, pos + t))); + for (t = 0; t < spec->n_grouped_digits; t++) { + Py_UCS4 c = PyUnicode_READ(kind, data, pos + t); + if (c > 127) { + PyErr_SetString(PyExc_SystemError, "non-ascii grouped digit"); + return -1; + } + PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c)); + } } pos += spec->n_grouped_digits; -- cgit v1.2.1 From e2360e9f21daa7f630fc6cd6a48938c2e4e1f845 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 12 Jan 2012 22:46:19 +0100 Subject: Issue #13748: Raw bytes literals can now be written with the `rb` prefix as well as `br`. --- Python/ast.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 48aef4815d..110754bfd4 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3744,13 +3744,18 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) int rawmode = 0; int need_encoding; if (isalpha(quote)) { - if (quote == 'b' || quote == 'B') { - quote = *++s; - *bytesmode = 1; - } - if (quote == 'r' || quote == 'R') { - quote = *++s; - rawmode = 1; + while (!*bytesmode || !rawmode) { + if (quote == 'b' || quote == 'B') { + quote = *++s; + *bytesmode = 1; + } + else if (quote == 'r' || quote == 'R') { + quote = *++s; + rawmode = 1; + } + else { + break; + } } } if (quote != '\'' && quote != '\"') { -- cgit v1.2.1 From e4f5fc423651e760f014159dce83273f9d54831c Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Fri, 13 Jan 2012 21:43:40 +1000 Subject: Implement PEP 380 - 'yield from' (closes #11682) --- Python/Python-ast.c | 27 ++++++- Python/ast.c | 21 ++++-- Python/ceval.c | 46 ++++++++++++ Python/compile.c | 8 +- Python/graminit.c | 190 ++++++++++++++++++++++++++---------------------- Python/opcode_targets.h | 2 +- Python/symtable.c | 19 ----- 7 files changed, 198 insertions(+), 115 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 8a101cf3b0..3121eb1bb7 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -231,7 +231,9 @@ static char *GeneratorExp_fields[]={ "generators", }; static PyTypeObject *Yield_type; +_Py_IDENTIFIER(is_from); static char *Yield_fields[]={ + "is_from", "value", }; static PyTypeObject *Compare_type; @@ -810,7 +812,7 @@ static int init_types(void) GeneratorExp_type = make_type("GeneratorExp", expr_type, GeneratorExp_fields, 2); if (!GeneratorExp_type) return 0; - Yield_type = make_type("Yield", expr_type, Yield_fields, 1); + Yield_type = make_type("Yield", expr_type, Yield_fields, 2); if (!Yield_type) return 0; Compare_type = make_type("Compare", expr_type, Compare_fields, 3); if (!Compare_type) return 0; @@ -1747,13 +1749,14 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, } expr_ty -Yield(expr_ty value, int lineno, int col_offset, PyArena *arena) +Yield(int is_from, expr_ty value, int lineno, int col_offset, PyArena *arena) { expr_ty p; p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; p->kind = Yield_kind; + p->v.Yield.is_from = is_from; p->v.Yield.value = value; p->lineno = lineno; p->col_offset = col_offset; @@ -2795,6 +2798,11 @@ ast2obj_expr(void* _o) case Yield_kind: result = PyType_GenericNew(Yield_type, NULL, NULL); if (!result) goto failed; + value = ast2obj_int(o->v.Yield.is_from); + if (!value) goto failed; + if (PyObject_SetAttrString(result, "is_from", value) == -1) + goto failed; + Py_DECREF(value); value = ast2obj_expr(o->v.Yield.value); if (!value) goto failed; if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) @@ -5337,8 +5345,21 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) return 1; } if (isinstance) { + int is_from; expr_ty value; + if (_PyObject_HasAttrId(obj, &PyId_is_from)) { + int res; + tmp = _PyObject_GetAttrId(obj, &PyId_is_from); + if (tmp == NULL) goto failed; + res = obj2ast_int(tmp, &is_from, arena); + if (res != 0) goto failed; + Py_XDECREF(tmp); + tmp = NULL; + } else { + PyErr_SetString(PyExc_TypeError, "required field \"is_from\" missing from Yield"); + return 1; + } if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; tmp = _PyObject_GetAttrId(obj, &PyId_value); @@ -5350,7 +5371,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) } else { value = NULL; } - *out = Yield(value, lineno, col_offset, arena); + *out = Yield(is_from, value, lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } diff --git a/Python/ast.c b/Python/ast.c index 110754bfd4..7080c65f34 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2369,13 +2369,24 @@ ast_for_expr(struct compiling *c, const node *n) } return ast_for_binop(c, n); case yield_expr: { + node *an = NULL; + node *en = NULL; + int is_from = 0; expr_ty exp = NULL; - if (NCH(n) == 2) { - exp = ast_for_testlist(c, CHILD(n, 1)); + if (NCH(n) > 1) + an = CHILD(n, 1); /* yield_arg */ + if (an) { + en = CHILD(an, NCH(an) - 1); + if (NCH(an) == 2) { + is_from = 1; + exp = ast_for_expr(c, en); + } + else + exp = ast_for_testlist(c, en); if (!exp) return NULL; } - return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); + return Yield(is_from, exp, LINENO(n), n->n_col_offset, c->c_arena); } case factor: if (NCH(n) == 1) { @@ -2399,7 +2410,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) /* arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) - argument: [test '='] test [comp_for] # Really [keyword '='] test + argument: [test '='] (test) [comp_for] # Really [keyword '='] test */ int i, nargs, nkeywords, ngens; @@ -2693,7 +2704,7 @@ ast_for_flow_stmt(struct compiling *c, const node *n) continue_stmt: 'continue' return_stmt: 'return' [testlist] yield_stmt: yield_expr - yield_expr: 'yield' testlist + yield_expr: 'yield' testlist | 'yield' 'from' test raise_stmt: 'raise' [test [',' test [',' test]]] */ node *ch; diff --git a/Python/ceval.c b/Python/ceval.c index ed82b9411a..134d1eec4b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1828,6 +1828,52 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) why = WHY_RETURN; goto fast_block_end; + TARGET(YIELD_FROM) + u = POP(); + x = PyObject_GetIter(u); + Py_DECREF(u); + if (x == NULL) + break; + /* x is now the iterator, make the first next() call */ + retval = (*Py_TYPE(x)->tp_iternext)(x); + if (!retval) { + /* iter may be exhausted */ + Py_CLEAR(x); + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + /* some other exception */ + break; + } + /* try to get return value from exception */ + PyObject *et, *ev, *tb; + PyErr_Fetch(&et, &ev, &tb); + Py_XDECREF(et); + Py_XDECREF(tb); + /* u is return value */ + u = NULL; + if (ev) { + u = PyObject_GetAttrString(ev, "value"); + Py_DECREF(ev); + if (u == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* some other exception */ + break; + } + PyErr_Clear(); + } + } + if (u == NULL) { + u = Py_None; + Py_INCREF(u); + } + PUSH(u); + continue; + } + /* x is iterator, retval is value to be yielded */ + f->f_yieldfrom = x; + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + goto fast_yield; + TARGET(YIELD_VALUE) retval = POP(); f->f_stacktop = stack_pointer; diff --git a/Python/compile.c b/Python/compile.c index 849f48785d..4d91f5024b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -840,6 +840,7 @@ opcode_stack_effect(int opcode, int oparg) case IMPORT_STAR: return -1; case YIELD_VALUE: + case YIELD_FROM: return 0; case POP_BLOCK: @@ -3318,7 +3319,12 @@ compiler_visit_expr(struct compiler *c, expr_ty e) else { ADDOP_O(c, LOAD_CONST, Py_None, consts); } - ADDOP(c, YIELD_VALUE); + if (e->v.Yield.is_from) { + ADDOP(c, YIELD_FROM); + } + else { + ADDOP(c, YIELD_VALUE); + } break; case Compare_kind: return compiler_compare(c, e); diff --git a/Python/graminit.c b/Python/graminit.c index a8af5833a9..e91e09ff93 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -1791,7 +1791,7 @@ static arc arcs_80_0[1] = { {167, 1}, }; static arc arcs_80_1[2] = { - {9, 2}, + {168, 2}, {0, 1}, }; static arc arcs_80_2[1] = { @@ -1802,171 +1802,188 @@ static state states_80[3] = { {2, arcs_80_1}, {1, arcs_80_2}, }; -static dfa dfas[81] = { +static arc arcs_81_0[2] = { + {73, 1}, + {9, 2}, +}; +static arc arcs_81_1[1] = { + {24, 2}, +}; +static arc arcs_81_2[1] = { + {0, 2}, +}; +static state states_81[3] = { + {2, arcs_81_0}, + {1, arcs_81_1}, + {1, arcs_81_2}, +}; +static dfa dfas[82] = { {256, "single_input", 0, 3, states_0, - "\004\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + "\004\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204\000"}, {257, "file_input", 0, 2, states_1, - "\204\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + "\204\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204\000"}, {258, "eval_input", 0, 3, states_2, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {259, "decorator", 0, 7, states_3, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 0, 2, states_4, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {261, "decorated", 0, 3, states_5, - "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {262, "funcdef", 0, 8, states_6, - "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {263, "parameters", 0, 4, states_7, - "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {264, "typedargslist", 0, 18, states_8, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {265, "tfpdef", 0, 4, states_9, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {266, "varargslist", 0, 18, states_10, - "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\200\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {267, "vfpdef", 0, 2, states_11, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {268, "stmt", 0, 2, states_12, - "\000\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204"}, + "\000\050\060\200\000\000\000\240\340\223\160\220\045\200\020\000\000\206\120\076\204\000"}, {269, "simple_stmt", 0, 4, states_13, - "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200\000"}, {270, "small_stmt", 0, 2, states_14, - "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + "\000\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200\000"}, {271, "expr_stmt", 0, 6, states_15, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {272, "testlist_star_expr", 0, 3, states_16, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {273, "augassign", 0, 2, states_17, - "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\376\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {274, "del_stmt", 0, 3, states_18, - "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {275, "pass_stmt", 0, 2, states_19, - "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {276, "flow_stmt", 0, 2, states_20, - "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\200"}, + "\000\000\000\000\000\000\000\000\340\001\000\000\000\000\000\000\000\000\000\000\200\000"}, {277, "break_stmt", 0, 2, states_21, - "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {278, "continue_stmt", 0, 2, states_22, - "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {279, "return_stmt", 0, 3, states_23, - "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {280, "yield_stmt", 0, 2, states_24, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000"}, {281, "raise_stmt", 0, 5, states_25, - "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"}, {282, "import_stmt", 0, 2, states_26, - "\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\022\000\000\000\000\000\000\000\000\000\000\000\000"}, {283, "import_name", 0, 3, states_27, - "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000"}, {284, "import_from", 0, 8, states_28, - "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000"}, {285, "import_as_name", 0, 4, states_29, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {286, "dotted_as_name", 0, 4, states_30, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {287, "import_as_names", 0, 3, states_31, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {288, "dotted_as_names", 0, 2, states_32, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {289, "dotted_name", 0, 2, states_33, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {290, "global_stmt", 0, 3, states_34, - "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000"}, {291, "nonlocal_stmt", 0, 3, states_35, - "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000"}, {292, "assert_stmt", 0, 5, states_36, - "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000"}, {293, "compound_stmt", 0, 2, states_37, - "\000\010\020\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004"}, + "\000\010\020\000\000\000\000\000\000\000\000\220\045\000\000\000\000\000\000\000\004\000"}, {294, "if_stmt", 0, 8, states_38, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, {295, "while_stmt", 0, 8, states_39, - "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000"}, {296, "for_stmt", 0, 10, states_40, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, {297, "try_stmt", 0, 13, states_41, - "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000"}, {298, "with_stmt", 0, 5, states_42, - "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000"}, {299, "with_item", 0, 4, states_43, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {300, "except_clause", 0, 5, states_44, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, {301, "suite", 0, 5, states_45, - "\004\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200"}, + "\004\040\040\200\000\000\000\240\340\223\160\000\000\200\020\000\000\206\120\076\200\000"}, {302, "test", 0, 6, states_46, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {303, "test_nocond", 0, 2, states_47, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {304, "lambdef", 0, 5, states_48, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, {305, "lambdef_nocond", 0, 5, states_49, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000"}, {306, "or_test", 0, 2, states_50, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000\000"}, {307, "and_test", 0, 2, states_51, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000\000"}, {308, "not_test", 0, 3, states_52, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\020\000\000\206\120\076\000\000"}, {309, "comparison", 0, 2, states_53, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {310, "comp_op", 0, 4, states_54, - "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\220\177\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\002\000\220\177\000\000\000\000\000\000"}, {311, "star_expr", 0, 3, states_55, - "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {312, "expr", 0, 2, states_56, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {313, "xor_expr", 0, 2, states_57, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {314, "and_expr", 0, 2, states_58, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {315, "shift_expr", 0, 2, states_59, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {316, "arith_expr", 0, 2, states_60, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {317, "term", 0, 2, states_61, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {318, "factor", 0, 3, states_62, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {319, "power", 0, 4, states_63, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000\000"}, {320, "atom", 0, 9, states_64, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\120\076\000\000"}, {321, "testlist_comp", 0, 5, states_65, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {322, "trailer", 0, 7, states_66, - "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000"}, + "\000\040\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\020\000\000\000"}, {323, "subscriptlist", 0, 3, states_67, - "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {324, "subscript", 0, 5, states_68, - "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\002\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {325, "sliceop", 0, 3, states_69, - "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {326, "exprlist", 0, 3, states_70, - "\000\040\040\200\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000"}, + "\000\040\040\200\000\000\000\000\000\200\000\000\000\000\000\000\000\206\120\076\000\000"}, {327, "testlist", 0, 3, states_71, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {328, "dictorsetmaker", 0, 11, states_72, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {329, "classdef", 0, 8, states_73, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000"}, {330, "arglist", 0, 8, states_74, - "\000\040\040\200\001\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\200\001\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {331, "argument", 0, 4, states_75, - "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000"}, + "\000\040\040\000\000\000\000\000\000\200\000\000\000\200\020\000\000\206\120\076\000\000"}, {332, "comp_iter", 0, 2, states_76, - "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\020\001\000\000\000\000\000\000\000\000\000"}, {333, "comp_for", 0, 6, states_77, - "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000"}, {334, "comp_if", 0, 4, states_78, - "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000"}, {335, "encoding_decl", 0, 2, states_79, - "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {336, "yield_expr", 0, 3, states_80, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000"}, + {337, "yield_arg", 0, 3, states_81, + "\000\040\040\000\000\000\000\000\000\202\000\000\000\200\020\000\000\206\120\076\000\000"}, }; -static label labels[168] = { +static label labels[169] = { {0, "EMPTY"}, {256, 0}, {4, 0}, @@ -2135,10 +2152,11 @@ static label labels[168] = { {334, 0}, {335, 0}, {1, "yield"}, + {337, 0}, }; grammar _PyParser_Grammar = { - 81, + 82, dfas, - {168, labels}, + {169, labels}, 256 }; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index a91da79be6..2d6bcda513 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -71,7 +71,7 @@ static void *opcode_targets[256] = { &&TARGET_STORE_LOCALS, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&_unknown_opcode, + &&TARGET_YIELD_FROM, &&_unknown_opcode, &&_unknown_opcode, &&TARGET_INPLACE_LSHIFT, diff --git a/Python/symtable.c b/Python/symtable.c index 824a53fc1b..1ce7f7036f 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -19,10 +19,6 @@ #define IMPORT_STAR_WARNING "import * only allowed at module level" -#define RETURN_VAL_IN_GENERATOR \ - "'return' with argument inside generator" - - static PySTEntryObject * ste_new(struct symtable *st, identifier name, _Py_block_ty block, void *key, int lineno, int col_offset) @@ -1133,14 +1129,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.Return.value) { VISIT(st, expr, s->v.Return.value); st->st_cur->ste_returns_value = 1; - if (st->st_cur->ste_generator) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - s->lineno, - s->col_offset); - return 0; - } } break; case Delete_kind: @@ -1345,13 +1333,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.Yield.value) VISIT(st, expr, e->v.Yield.value); st->st_cur->ste_generator = 1; - if (st->st_cur->ste_returns_value) { - PyErr_SetString(PyExc_SyntaxError, - RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - e->lineno, e->col_offset); - return 0; - } break; case Compare_kind: VISIT(st, expr, e->v.Compare.left); -- cgit v1.2.1 From 1434e995657f5525a55584535d023dbe0ce2af24 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 13 Jan 2012 18:52:16 +0100 Subject: Issue #13645: pyc files now contain the size of the corresponding source code, to avoid timestamp collisions (especially on filesystems with a low timestamp resolution) when checking for freshness of the bytecode. --- Python/Python-ast.c | 2 +- Python/import.c | 26 ++++++++++++++++++++------ Python/pythonrun.c | 2 ++ 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 3121eb1bb7..2882bbc073 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2800,7 +2800,7 @@ ast2obj_expr(void* _o) if (!result) goto failed; value = ast2obj_int(o->v.Yield.is_from); if (!value) goto failed; - if (PyObject_SetAttrString(result, "is_from", value) == -1) + if (_PyObject_SetAttrId(result, &PyId_is_from, value) == -1) goto failed; Py_DECREF(value); value = ast2obj_expr(o->v.Yield.value); diff --git a/Python/import.c b/Python/import.c index c7541316b5..4efc36923a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -104,6 +104,7 @@ typedef unsigned short mode_t; Python 3.2a2 3180 (add DELETE_DEREF) Python 3.3a0 3190 __class__ super closure changed Python 3.3a0 3200 (__qualname__ added) + 3210 (added size modulo 2**32 to the pyc header) */ /* MAGIC must change whenever the bytecode emitted by the compiler may no @@ -116,7 +117,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 (3200 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3210 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" /* Current magic word and string tag as globals. */ @@ -1071,11 +1072,12 @@ make_source_pathname(PyObject *path) Doesn't set an exception. */ static FILE * -check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname) +check_compiled_module(PyObject *pathname, struct stat *srcstat, PyObject *cpathname) { FILE *fp; long magic; long pyc_mtime; + long pyc_size; fp = _Py_fopen(cpathname, "rb"); if (fp == NULL) @@ -1088,12 +1090,19 @@ check_compiled_module(PyObject *pathname, time_t mtime, PyObject *cpathname) return NULL; } pyc_mtime = PyMarshal_ReadLongFromFile(fp); - if (pyc_mtime != mtime) { + if (pyc_mtime != srcstat->st_mtime) { if (Py_VerboseFlag) PySys_FormatStderr("# %R has bad mtime\n", cpathname); fclose(fp); return NULL; } + pyc_size = PyMarshal_ReadLongFromFile(fp); + if (pyc_size != (srcstat->st_size & 0xFFFFFFFF)) { + if (Py_VerboseFlag) + PySys_FormatStderr("# %R has bad size\n", cpathname); + fclose(fp); + return NULL; + } if (Py_VerboseFlag) PySys_FormatStderr("# %R matches %R\n", cpathname, pathname); return fp; @@ -1136,6 +1145,8 @@ load_compiled_module(PyObject *name, PyObject *cpathname, FILE *fp) "Bad magic number in %R", cpathname); return NULL; } + /* Skip mtime and size */ + (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); co = read_compiled_module(cpathname, fp); if (co == NULL) @@ -1196,6 +1207,7 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, Py_UCS4 *cpathname_ucs4; FILE *fp; time_t mtime = srcstat->st_mtime; + long size = srcstat->st_size & 0xFFFFFFFF; PyObject *cpathname_tmp; #ifdef MS_WINDOWS /* since Windows uses different permissions */ mode_t mode = srcstat->st_mode & ~S_IEXEC; @@ -1326,14 +1338,16 @@ write_compiled_module(PyCodeObject *co, PyObject *cpathname, return; } PyMarshal_WriteLongToFile(pyc_magic, fp, Py_MARSHAL_VERSION); - /* First write a 0 for mtime */ + /* First write a 0 for mtime and size */ + PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION); PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION); fflush(fp); - /* Now write the true mtime */ + /* Now write the true mtime and size */ fseek(fp, 4L, 0); assert(mtime < LONG_MAX); PyMarshal_WriteLongToFile((long)mtime, fp, Py_MARSHAL_VERSION); + PyMarshal_WriteLongToFile(size, fp, Py_MARSHAL_VERSION); if (fflush(fp) != 0 || ferror(fp)) { if (Py_VerboseFlag) PySys_FormatStderr("# can't write %R\n", cpathname); @@ -1478,7 +1492,7 @@ load_source_module(PyObject *name, PyObject *pathname, FILE *fp) cpathname = make_compiled_pathname(pathname, !Py_OptimizeFlag); if (cpathname != NULL) - fpc = check_compiled_module(pathname, st.st_mtime, cpathname); + fpc = check_compiled_module(pathname, &st, cpathname); else fpc = NULL; diff --git a/Python/pythonrun.c b/Python/pythonrun.c index c8d1e90074..761110a86c 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1844,6 +1844,8 @@ run_pyc_file(FILE *fp, const char *filename, PyObject *globals, "Bad magic number in .pyc file"); return NULL; } + /* Skip mtime and size */ + (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); v = PyMarshal_ReadLastObjectFromFile(fp); fclose(fp); -- cgit v1.2.1 From a22a60af5d3f1d04ae5aa3a96e6b94ca94777405 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Fri, 13 Jan 2012 19:41:25 +0100 Subject: Closes #13761: add a "flush" keyword argument to print(). --- Python/bltinmodule.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index d1630cc3da..81402fc8c5 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1484,15 +1484,15 @@ equivalent to (x**y) % z, but may be more efficient (e.g. for longs)."); static PyObject * builtin_print(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"sep", "end", "file", 0}; + static char *kwlist[] = {"sep", "end", "file", "flush", 0}; static PyObject *dummy_args; - PyObject *sep = NULL, *end = NULL, *file = NULL; + PyObject *sep = NULL, *end = NULL, *file = NULL, *flush = NULL; int i, err; if (dummy_args == NULL && !(dummy_args = PyTuple_New(0))) - return NULL; - if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOO:print", - kwlist, &sep, &end, &file)) + return NULL; + if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOOO:print", + kwlist, &sep, &end, &file, &flush)) return NULL; if (file == NULL || file == Py_None) { file = PySys_GetObject("stdout"); @@ -1543,6 +1543,20 @@ builtin_print(PyObject *self, PyObject *args, PyObject *kwds) if (err) return NULL; + if (flush != NULL) { + PyObject *tmp; + int do_flush = PyObject_IsTrue(flush); + if (do_flush == -1) + return NULL; + else if (do_flush) { + tmp = PyObject_CallMethod(file, "flush", ""); + if (tmp == NULL) + return NULL; + else + Py_DECREF(tmp); + } + } + Py_RETURN_NONE; } -- cgit v1.2.1 From 8a26917ad2c8bc07ba5389c9ad599f1eb0a2936e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 13 Jan 2012 14:54:31 -0500 Subject: NULL and no exception set from tp_iternext means StopIteration --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 134d1eec4b..98219b0c9d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1839,7 +1839,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (!retval) { /* iter may be exhausted */ Py_CLEAR(x); - if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + if (PyErr_Occurred() && + !PyErr_ExceptionMatches(PyExc_StopIteration)) { /* some other exception */ break; } -- cgit v1.2.1 From 3705fefce326453806de7400c01106a85f81908b Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 13 Jan 2012 21:08:49 +0100 Subject: Fix compilation with C89 compilers (Windows...) --- 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 98219b0c9d..e2d96c5c44 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1837,6 +1837,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* x is now the iterator, make the first next() call */ retval = (*Py_TYPE(x)->tp_iternext)(x); if (!retval) { + PyObject *et, *ev, *tb; /* iter may be exhausted */ Py_CLEAR(x); if (PyErr_Occurred() && @@ -1845,7 +1846,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; } /* try to get return value from exception */ - PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); Py_XDECREF(et); Py_XDECREF(tb); -- cgit v1.2.1 From 37fe2bd5e9be127591b1e39efe50fc0c3348b5ab Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 14 Jan 2012 08:58:23 -0500 Subject: make YieldFrom its own distinct from Yield (closes #13780) --- Python/Python-ast.c | 62 ++++++++++++++++++++++++++++++++++++++++------------- Python/ast.c | 8 ++++++- Python/compile.c | 10 ++++++--- Python/symtable.c | 8 +++++-- 4 files changed, 67 insertions(+), 21 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2882bbc073..2603b812f0 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -231,9 +231,11 @@ static char *GeneratorExp_fields[]={ "generators", }; static PyTypeObject *Yield_type; -_Py_IDENTIFIER(is_from); static char *Yield_fields[]={ - "is_from", + "value", +}; +static PyTypeObject *YieldFrom_type; +static char *YieldFrom_fields[]={ "value", }; static PyTypeObject *Compare_type; @@ -812,8 +814,10 @@ static int init_types(void) GeneratorExp_type = make_type("GeneratorExp", expr_type, GeneratorExp_fields, 2); if (!GeneratorExp_type) return 0; - Yield_type = make_type("Yield", expr_type, Yield_fields, 2); + Yield_type = make_type("Yield", expr_type, Yield_fields, 1); if (!Yield_type) return 0; + YieldFrom_type = make_type("YieldFrom", expr_type, YieldFrom_fields, 1); + if (!YieldFrom_type) return 0; Compare_type = make_type("Compare", expr_type, Compare_fields, 3); if (!Compare_type) return 0; Call_type = make_type("Call", expr_type, Call_fields, 5); @@ -1749,20 +1753,33 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset, } expr_ty -Yield(int is_from, expr_ty value, int lineno, int col_offset, PyArena *arena) +Yield(expr_ty value, int lineno, int col_offset, PyArena *arena) { expr_ty p; p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); if (!p) return NULL; p->kind = Yield_kind; - p->v.Yield.is_from = is_from; p->v.Yield.value = value; p->lineno = lineno; p->col_offset = col_offset; return p; } +expr_ty +YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena) +{ + expr_ty p; + p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = YieldFrom_kind; + p->v.YieldFrom.value = value; + p->lineno = lineno; + p->col_offset = col_offset; + return p; +} + expr_ty Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno, int col_offset, PyArena *arena) @@ -2798,12 +2815,16 @@ ast2obj_expr(void* _o) case Yield_kind: result = PyType_GenericNew(Yield_type, NULL, NULL); if (!result) goto failed; - value = ast2obj_int(o->v.Yield.is_from); + value = ast2obj_expr(o->v.Yield.value); if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_is_from, value) == -1) + if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_expr(o->v.Yield.value); + break; + case YieldFrom_kind: + result = PyType_GenericNew(YieldFrom_type, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(o->v.YieldFrom.value); if (!value) goto failed; if (_PyObject_SetAttrId(result, &PyId_value, value) == -1) goto failed; @@ -5345,21 +5366,30 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) return 1; } if (isinstance) { - int is_from; expr_ty value; - if (_PyObject_HasAttrId(obj, &PyId_is_from)) { + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; - tmp = _PyObject_GetAttrId(obj, &PyId_is_from); + tmp = _PyObject_GetAttrId(obj, &PyId_value); if (tmp == NULL) goto failed; - res = obj2ast_int(tmp, &is_from, arena); + res = obj2ast_expr(tmp, &value, arena); if (res != 0) goto failed; Py_XDECREF(tmp); tmp = NULL; } else { - PyErr_SetString(PyExc_TypeError, "required field \"is_from\" missing from Yield"); - return 1; + value = NULL; } + *out = Yield(value, lineno, col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } + isinstance = PyObject_IsInstance(obj, (PyObject*)YieldFrom_type); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty value; + if (_PyObject_HasAttrId(obj, &PyId_value)) { int res; tmp = _PyObject_GetAttrId(obj, &PyId_value); @@ -5371,7 +5401,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena) } else { value = NULL; } - *out = Yield(is_from, value, lineno, col_offset, arena); + *out = YieldFrom(value, lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -6928,6 +6958,8 @@ PyInit__ast(void) (PyObject*)GeneratorExp_type) < 0) return NULL; if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return NULL; + if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) < + 0) return NULL; if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0) return NULL; if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return diff --git a/Python/ast.c b/Python/ast.c index 7080c65f34..3417fe31a4 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -223,6 +223,9 @@ validate_expr(expr_ty exp, expr_context_ty ctx) validate_expr(exp->v.DictComp.value, Load); case Yield_kind: return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load); + case YieldFrom_kind: + return !exp->v.YieldFrom.value || + validate_expr(exp->v.YieldFrom.value, Load); case Compare_kind: if (!asdl_seq_LEN(exp->v.Compare.comparators)) { PyErr_SetString(PyExc_ValueError, "Compare with no comparators"); @@ -942,6 +945,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) expr_name = "generator expression"; break; case Yield_kind: + case YieldFrom_kind: expr_name = "yield expression"; break; case ListComp_kind: @@ -2386,7 +2390,9 @@ ast_for_expr(struct compiling *c, const node *n) if (!exp) return NULL; } - return Yield(is_from, exp, LINENO(n), n->n_col_offset, c->c_arena); + if (is_from) + return YieldFrom(exp, LINENO(n), n->n_col_offset, c->c_arena); + return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); } case factor: if (NCH(n) == 1) { diff --git a/Python/compile.c b/Python/compile.c index 4d91f5024b..b64c800e19 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3311,21 +3311,25 @@ compiler_visit_expr(struct compiler *c, expr_ty e) case DictComp_kind: return compiler_dictcomp(c, e); case Yield_kind: + case YieldFrom_kind: { + expr_ty value; if (c->u->u_ste->ste_type != FunctionBlock) return compiler_error(c, "'yield' outside function"); - if (e->v.Yield.value) { - VISIT(c, expr, e->v.Yield.value); + value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value; + if (value) { + VISIT(c, expr, value); } else { ADDOP_O(c, LOAD_CONST, Py_None, consts); } - if (e->v.Yield.is_from) { + if (e->kind == YieldFrom_kind) { ADDOP(c, YIELD_FROM); } else { ADDOP(c, YIELD_VALUE); } break; + } case Compare_kind: return compiler_compare(c, e); case Call_kind: diff --git a/Python/symtable.c b/Python/symtable.c index 1ce7f7036f..b6228356bf 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1330,10 +1330,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e) return 0; break; case Yield_kind: - if (e->v.Yield.value) - VISIT(st, expr, e->v.Yield.value); + case YieldFrom_kind: { + expr_ty value; + value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value; + if (value) + VISIT(st, expr, value); st->st_cur->ste_generator = 1; break; + } case Compare_kind: VISIT(st, expr, e->v.Compare.left); VISIT_SEQ(st, expr, e->v.Compare.comparators); -- cgit v1.2.1 From 504caad994c3ea81d8b6dd171dd6b3dcd7a495b4 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:42:36 -0500 Subject: rewrite such that this actually makes sense --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 3417fe31a4..3440308ea9 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -490,7 +490,7 @@ PyAST_Validate(mod_ty mod) return res; } -/* This is down here, so defines like "test" don't intefere with access AST above. */ +/* This is done here, so defines like "test" don't intefere with AST use above. */ #include "grammar.h" #include "parsetok.h" #include "graminit.h" -- cgit v1.2.1 From 5d471a4227fc21ec6f045c051dd3132f53003201 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:47:42 -0500 Subject: PyUnicode_DecodeUTF8 will always return a ready string --- Python/ast.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 3440308ea9..df2c63da1b 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -532,8 +532,9 @@ new_identifier(const char* n, PyArena *arena) { _Py_IDENTIFIER(normalize); PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); - if (!id || PyUnicode_READY(id) == -1) + if (!id) return NULL; + assert(PyUnicode_IS_READY(id)); /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ if (PyUnicode_MAX_CHAR_VALUE((PyUnicodeObject *)id) >= 128) { -- cgit v1.2.1 From e2ad70658b5eb85b2efa295038ab26a9442c290a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:49:20 -0500 Subject: use helpful PyUnicode_IS_ASCII macro --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index df2c63da1b..9776a6a151 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -537,7 +537,7 @@ new_identifier(const char* n, PyArena *arena) assert(PyUnicode_IS_READY(id)); /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ - if (PyUnicode_MAX_CHAR_VALUE((PyUnicodeObject *)id) >= 128) { + if (PyUnicode_IS_ASCII(id)) { PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); PyObject *id2; if (!m) -- cgit v1.2.1 From 52c6328874a14ecd14be59a7e88b3977b8fcf07b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:50:48 -0500 Subject: fix possible refleaks --- Python/ast.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 9776a6a151..c70073cdab 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -540,13 +540,15 @@ new_identifier(const char* n, PyArena *arena) if (PyUnicode_IS_ASCII(id)) { PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); PyObject *id2; - if (!m) + if (!m) { + Py_DECREF(id); return NULL; + } id2 = _PyObject_CallMethodId(m, &PyId_normalize, "sO", "NFKC", id); Py_DECREF(m); + Py_DECREF(id); if (!id2) return NULL; - Py_DECREF(id); id = id2; } PyUnicode_InternInPlace(&id); -- cgit v1.2.1 From efbeeaa49dc5a86e0d0d0a977a958c0010e42492 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:55:53 -0500 Subject: invert condition (head bang) --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index c70073cdab..78b4126cdf 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -537,7 +537,7 @@ new_identifier(const char* n, PyArena *arena) assert(PyUnicode_IS_READY(id)); /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ - if (PyUnicode_IS_ASCII(id)) { + if (!PyUnicode_IS_ASCII(id)) { PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); PyObject *id2; if (!m) { -- cgit v1.2.1 From 5691bbe76b03e36cf70c9b9059dc363621be3a55 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 09:56:35 -0500 Subject: fix spelling --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 78b4126cdf..5d2b35d860 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -490,7 +490,7 @@ PyAST_Validate(mod_ty mod) return res; } -/* This is done here, so defines like "test" don't intefere with AST use above. */ +/* This is done here, so defines like "test" don't interfere with AST use above. */ #include "grammar.h" #include "parsetok.h" #include "graminit.h" -- cgit v1.2.1 From 322bdedc8730c1a58bbec325be774252a3d4d179 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 17:22:31 -0500 Subject: streamline normalizer identification a bit --- Python/ast.c | 80 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 25 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 5d2b35d860..26163f7132 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -500,6 +500,8 @@ struct compiling { char *c_encoding; /* source encoding */ PyArena *c_arena; /* arena for allocating memeory */ const char *c_filename; /* filename */ + PyObject *c_normalize; /* Normalization function from unicodedata. */ + PyObject *c_normalize_args; /* Normalization argument tuple. */ }; static asdl_seq *seq_for_testlist(struct compiling *, const node *); @@ -527,36 +529,54 @@ static PyObject *parsestrplus(struct compiling *, const node *n, #define COMP_LISTCOMP 1 #define COMP_SETCOMP 2 +static int +init_normalization(struct compiling *c) +{ + PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); + if (!m) + return 0; + c->c_normalize = PyObject_GetAttrString(m, "normalize"); + Py_DECREF(m); + if (!c->c_normalize) + return 0; + c->c_normalize_args = Py_BuildValue("(sN)", "NFKC", Py_None); + PyTuple_SET_ITEM(c->c_normalize_args, 1, NULL); + if (!c->c_normalize_args) { + Py_CLEAR(c->c_normalize); + return 0; + } + return 1; +} + static identifier -new_identifier(const char* n, PyArena *arena) +new_identifier(const char* n, struct compiling *c) { - _Py_IDENTIFIER(normalize); PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); if (!id) return NULL; + /* PyUnicode_DecodeUTF8 should always return a ready string. */ assert(PyUnicode_IS_READY(id)); /* Check whether there are non-ASCII characters in the identifier; if so, normalize to NFKC. */ if (!PyUnicode_IS_ASCII(id)) { - PyObject *m = PyImport_ImportModuleNoBlock("unicodedata"); PyObject *id2; - if (!m) { + if (!c->c_normalize && !init_normalization(c)) { Py_DECREF(id); return NULL; } - id2 = _PyObject_CallMethodId(m, &PyId_normalize, "sO", "NFKC", id); - Py_DECREF(m); + PyTuple_SET_ITEM(c->c_normalize_args, 1, id); + id2 = PyObject_Call(c->c_normalize, c->c_normalize_args, NULL); Py_DECREF(id); if (!id2) return NULL; id = id2; } PyUnicode_InternInPlace(&id); - PyArena_AddPyObject(arena, id); + PyArena_AddPyObject(c->c_arena, id); return id; } -#define NEW_IDENTIFIER(n) new_identifier(STR(n), c->c_arena) +#define NEW_IDENTIFIER(n) new_identifier(STR(n), c) /* This routine provides an invalid object for the syntax error. The outermost routine must unpack this error and create the @@ -706,13 +726,14 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, stmt_ty s; node *ch; struct compiling c; + mod_ty res = NULL; if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) { c.c_encoding = "utf-8"; if (TYPE(n) == encoding_decl) { #if 0 ast_error(n, "encoding declaration in Unicode string"); - goto error; + goto out; #endif n = CHILD(n, 0); } @@ -725,13 +746,14 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, } c.c_arena = arena; c.c_filename = filename; + c.c_normalize = c.c_normalize_args = NULL; k = 0; switch (TYPE(n)) { case file_input: stmts = asdl_seq_new(num_stmts(n), arena); if (!stmts) - return NULL; + goto out; for (i = 0; i < NCH(n) - 1; i++) { ch = CHILD(n, i); if (TYPE(ch) == NEWLINE) @@ -741,7 +763,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, if (num == 1) { s = ast_for_stmt(&c, ch); if (!s) - goto error; + goto out; asdl_seq_SET(stmts, k++, s); } else { @@ -750,42 +772,44 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, for (j = 0; j < num; j++) { s = ast_for_stmt(&c, CHILD(ch, j * 2)); if (!s) - goto error; + goto out; asdl_seq_SET(stmts, k++, s); } } } - return Module(stmts, arena); + res = Module(stmts, arena); + break; case eval_input: { expr_ty testlist_ast; /* XXX Why not comp_for here? */ testlist_ast = ast_for_testlist(&c, CHILD(n, 0)); if (!testlist_ast) - goto error; - return Expression(testlist_ast, arena); + goto out; + res = Expression(testlist_ast, arena); + break; } case single_input: if (TYPE(CHILD(n, 0)) == NEWLINE) { stmts = asdl_seq_new(1, arena); if (!stmts) - goto error; + goto out; asdl_seq_SET(stmts, 0, Pass(n->n_lineno, n->n_col_offset, arena)); if (!asdl_seq_GET(stmts, 0)) - goto error; - return Interactive(stmts, arena); + goto out; + res = Interactive(stmts, arena); } else { n = CHILD(n, 0); num = num_stmts(n); stmts = asdl_seq_new(num, arena); if (!stmts) - goto error; + goto out; if (num == 1) { s = ast_for_stmt(&c, n); if (!s) - goto error; + goto out; asdl_seq_SET(stmts, 0, s); } else { @@ -796,21 +820,27 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, break; s = ast_for_stmt(&c, CHILD(n, i)); if (!s) - goto error; + goto out; asdl_seq_SET(stmts, i / 2, s); } } - return Interactive(stmts, arena); + res = Interactive(stmts, arena); + break; } default: PyErr_Format(PyExc_SystemError, "invalid node %d for PyAST_FromNode", TYPE(n)); - goto error; + goto out; + } + out: + if (c.c_normalize) { + Py_DECREF(c.c_normalize); + PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL); + Py_DECREF(c.c_normalize_args); } - error: ast_error_finish(filename); - return NULL; + return res; } /* Return the AST repr. of the operator represented as syntax (|, ^, etc.) -- cgit v1.2.1 From 25ed3f525d49eb20289d5d77cad1c1721b6d3926 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 17:29:05 -0500 Subject: move LINENO define to where it actually belongs --- Python/ast.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 26163f7132..66b85b5a7f 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -521,10 +521,6 @@ static PyObject *parsestr(struct compiling *, const node *n, int *bytesmode); static PyObject *parsestrplus(struct compiling *, const node *n, int *bytesmode); -#ifndef LINENO -#define LINENO(n) ((n)->n_lineno) -#endif - #define COMP_GENEXP 0 #define COMP_LISTCOMP 1 #define COMP_SETCOMP 2 -- cgit v1.2.1 From 161300f778e6c5e14368be8e51a7d98ab833a159 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 17:31:43 -0500 Subject: only finish error if one occurred --- Python/ast.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 66b85b5a7f..ef161b6f25 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -835,7 +835,8 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL); Py_DECREF(c.c_normalize_args); } - ast_error_finish(filename); + if (!res) + ast_error_finish(filename); return res; } -- cgit v1.2.1 From 83f12dabf419e3cecad941805d87e465a4df2e47 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 17:44:12 -0500 Subject: break out switch at correct place --- Python/ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index ef161b6f25..55faf97c4f 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -822,8 +822,8 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, } res = Interactive(stmts, arena); - break; } + break; default: PyErr_Format(PyExc_SystemError, "invalid node %d for PyAST_FromNode", TYPE(n)); -- cgit v1.2.1 From 9d143481fc77ab2f6355c58fa714da55e97467db Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 16 Jan 2012 18:02:21 -0500 Subject: fix indentation --- Python/ast.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index 55faf97c4f..c56564279b 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -2530,13 +2530,13 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) * then is very confusing. */ if (e->kind == Lambda_kind) { - ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); - return NULL; + ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); + return NULL; } else if (e->kind != Name_kind) { - ast_error(CHILD(ch, 0), "keyword can't be an expression"); - return NULL; + ast_error(CHILD(ch, 0), "keyword can't be an expression"); + return NULL; } else if (forbidden_name(e->v.Name.id, ch, 1)) { - return NULL; + return NULL; } key = e->v.Name.id; for (k = 0; k < nkeywords; k++) { -- cgit v1.2.1 From b9c284bcd8ba48686ceb806693ce1e4bfad7c149 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 18 Jan 2012 21:45:15 +0100 Subject: Finally fix all test_capi refleaks --- Python/_warnings.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/_warnings.c b/Python/_warnings.c index adebd51ed2..f33e477ad7 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -958,23 +958,30 @@ _PyWarnings_Init(void) if (m == NULL) return NULL; - _filters = init_filters(); - if (_filters == NULL) - return NULL; + if (_filters == NULL) { + _filters = init_filters(); + if (_filters == NULL) + return NULL; + } Py_INCREF(_filters); if (PyModule_AddObject(m, "filters", _filters) < 0) return NULL; - _once_registry = PyDict_New(); - if (_once_registry == NULL) - return NULL; + if (_once_registry == NULL) { + _once_registry = PyDict_New(); + if (_once_registry == NULL) + return NULL; + } Py_INCREF(_once_registry); if (PyModule_AddObject(m, "_onceregistry", _once_registry) < 0) return NULL; - _default_action = PyUnicode_FromString("default"); - if (_default_action == NULL) - return NULL; + if (_default_action == NULL) { + _default_action = PyUnicode_FromString("default"); + if (_default_action == NULL) + return NULL; + } + Py_INCREF(_default_action); if (PyModule_AddObject(m, "_defaultaction", _default_action) < 0) return NULL; return m; -- cgit v1.2.1 From fb993800cf884241d1b83007707e5290e29c1d37 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Thu, 19 Jan 2012 01:08:41 -0600 Subject: Issue #12705: Raise SyntaxError when compiling multiple statements as single interactive statement --- Python/pythonrun.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index bff04de599..44b817f546 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -2129,6 +2129,9 @@ err_input(perrdetail *err) case E_IDENTIFIER: msg = "invalid character in identifier"; break; + case E_BADSINGLE: + msg = "multiple statements found while compiling a single statement"; + break; default: fprintf(stderr, "error=%d\n", err->error); msg = "unknown parsing error"; -- cgit v1.2.1 From a492ac5b62a9caa2282f4db44ebb767d1f1cfd0e Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Thu, 19 Jan 2012 20:04:28 -0500 Subject: Improve exception text. Closes issue 13811. --- Python/formatter_unicode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 12b880d7e7..db6364f513 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -241,8 +241,8 @@ parse_internal_render_format_spec(PyObject *format_spec, /* Finally, parse the type field. */ if (end-pos > 1) { - /* More than one char remain, invalid conversion spec. */ - PyErr_Format(PyExc_ValueError, "Invalid conversion specification"); + /* More than one char remain, invalid format specifier. */ + PyErr_Format(PyExc_ValueError, "Invalid format specifier"); return 0; } -- cgit v1.2.1 From 588f4583fb3bb584abb3f2277f3d84ef6dc8c53d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 21 Jan 2012 15:50:49 +0100 Subject: Issue #13706: Support non-ASCII fill characters --- Python/formatter_unicode.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index db6364f513..609ac16899 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -274,12 +274,8 @@ parse_internal_render_format_spec(PyObject *format_spec, } } - if (format->fill_char > 127 || format->align > 127 || - format->sign > 127) { - PyErr_SetString(PyExc_ValueError, "fill character too large"); - return 0; - } - + assert (format->align <= 127); + assert (format->sign <= 127); return 1; } @@ -563,10 +559,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, Py_ssize_t t; for (t = 0; t < spec->n_prefix; t++) { Py_UCS4 c = PyUnicode_READ(kind, data, pos + t); - if (c > 127) { - PyErr_SetString(PyExc_SystemError, "prefix not ASCII"); - return -1; - } + assert (c <= 127); PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c)); } } @@ -722,6 +715,9 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format) calc_padding(len, format->width, format->align, &lpad, &rpad, &total); + if (lpad != 0 || rpad != 0) + maxchar = Py_MAX(maxchar, format->fill_char); + /* allocate the resulting string */ result = PyUnicode_New(total, maxchar); if (result == NULL) @@ -791,21 +787,18 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, /* taken from unicodeobject.c formatchar() */ /* Integer input truncated to a character */ -/* XXX: won't work for int */ x = PyLong_AsLong(value); if (x == -1 && PyErr_Occurred()) goto done; if (x < 0 || x > 0x10ffff) { PyErr_SetString(PyExc_OverflowError, - "%c arg not in range(0x110000) " - "(wide Python build)"); + "%c arg not in range(0x110000)"); goto done; } tmp = PyUnicode_FromOrdinal(x); inumeric_chars = 0; n_digits = 1; - if (x > maxchar) - maxchar = x; + maxchar = Py_MAX(maxchar, x); /* As a sort-of hack, we tell calc_number_widths that we only have "remainder" characters. calc_number_widths thinks @@ -882,6 +875,9 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars, inumeric_chars + n_digits, n_remainder, 0, &locale, format); + if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) + maxchar = Py_MAX(maxchar, format->fill_char); + /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); if (!result) @@ -1020,6 +1016,9 @@ format_float_internal(PyObject *value, index + n_digits, n_remainder, has_decimal, &locale, format); + if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) + maxchar = Py_MAX(maxchar, format->fill_char); + /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); if (result == NULL) @@ -1219,6 +1218,11 @@ format_complex_internal(PyObject *value, calc_padding(n_re_total + n_im_total + 1 + add_parens * 2, format->width, format->align, &lpad, &rpad, &total); + if (re_spec.n_lpadding || re_spec.n_spadding || re_spec.n_rpadding + || im_spec.n_lpadding || im_spec.n_spadding || im_spec.n_rpadding + || lpad || rpad) + maxchar = Py_MAX(maxchar, format->fill_char); + result = PyUnicode_New(total, maxchar); if (result == NULL) goto done; -- cgit v1.2.1 From a89a01f7a48f0e422ff34ee40f1f0c16985dd5a8 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 22 Jan 2012 11:24:29 -0500 Subject: use the static identifier api for looking up special methods I had to move the static identifier code from unicodeobject.h to object.h in order for this to work. --- Python/ceval.c | 15 ++++++++------- Python/sysmodule.c | 6 +++--- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index e2d96c5c44..06bff4c169 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -138,7 +138,7 @@ static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); static PyObject * unicode_concatenate(PyObject *, PyObject *, PyFrameObject *, unsigned char *); -static PyObject * special_lookup(PyObject *, char *, PyObject **); +static PyObject * special_lookup(PyObject *, _Py_Identifier *); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -2540,13 +2540,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(SETUP_WITH) { - static PyObject *exit, *enter; + _Py_IDENTIFIER(__exit__); + _Py_IDENTIFIER(__enter__); w = TOP(); - x = special_lookup(w, "__exit__", &exit); + x = special_lookup(w, &PyId___exit__); if (!x) break; SET_TOP(x); - u = special_lookup(w, "__enter__", &enter); + u = special_lookup(w, &PyId___enter__); Py_DECREF(w); if (!u) { x = NULL; @@ -3440,12 +3441,12 @@ fail: /* Jump here from prelude on failure */ static PyObject * -special_lookup(PyObject *o, char *meth, PyObject **cache) +special_lookup(PyObject *o, _Py_Identifier *id) { PyObject *res; - res = _PyObject_LookupSpecial(o, meth, cache); + res = _PyObject_LookupSpecial(o, id); if (res == NULL && !PyErr_Occurred()) { - PyErr_SetObject(PyExc_AttributeError, *cache); + PyErr_SetObject(PyExc_AttributeError, id->object); return NULL; } return res; diff --git a/Python/sysmodule.c b/Python/sysmodule.c index ab0008e44c..d1517d33f6 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -814,10 +814,11 @@ static PyObject * sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) { PyObject *res = NULL; - static PyObject *str__sizeof__ = NULL, *gc_head_size = NULL; + static PyObject *gc_head_size = NULL; static char *kwlist[] = {"object", "default", 0}; PyObject *o, *dflt = NULL; PyObject *method; + _Py_IDENTIFIER(__sizeof__); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", kwlist, &o, &dflt)) @@ -834,8 +835,7 @@ sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) if (PyType_Ready(Py_TYPE(o)) < 0) return NULL; - method = _PyObject_LookupSpecial(o, "__sizeof__", - &str__sizeof__); + method = _PyObject_LookupSpecial(o, &PyId___sizeof__); if (method == NULL) { if (!PyErr_Occurred()) PyErr_Format(PyExc_TypeError, -- cgit v1.2.1 From 9d06170f8ed5c860eaf1ba30fb10e4e8a5e79b6b Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Mon, 23 Jan 2012 22:42:19 +0100 Subject: Fix compilation warnings (seen on win32 buildbot) --- Python/formatter_unicode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 609ac16899..db8c27c9e4 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -682,7 +682,7 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format) Py_ssize_t pos; Py_ssize_t len = PyUnicode_GET_LENGTH(value); PyObject *result = NULL; - int maxchar = 127; + Py_UCS4 maxchar = 127; /* sign is not allowed on strings */ if (format->sign != '\0') { @@ -749,7 +749,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, IntOrLongToString tostring) { PyObject *result = NULL; - int maxchar = 127; + Py_UCS4 maxchar = 127; PyObject *tmp = NULL; Py_ssize_t inumeric_chars; Py_UCS4 sign_char = '\0'; @@ -926,7 +926,7 @@ format_float_internal(PyObject *value, NumberFieldWidths spec; int flags = 0; PyObject *result = NULL; - int maxchar = 127; + Py_UCS4 maxchar = 127; Py_UCS4 sign_char = '\0'; int float_type; /* Used to see if we have a nan, inf, or regular float. */ PyObject *unicode_tmp = NULL; @@ -1070,7 +1070,7 @@ format_complex_internal(PyObject *value, NumberFieldWidths im_spec; int flags = 0; PyObject *result = NULL; - int maxchar = 127; + Py_UCS4 maxchar = 127; int rkind; void *rdata; Py_ssize_t index; -- cgit v1.2.1 From 597ed82954be94ee0d4cf498586e4eb4e4c301aa Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Mon, 23 Jan 2012 23:20:43 +0100 Subject: Silence last compilation warning. --- Python/formatter_unicode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index db8c27c9e4..eee99134ad 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -798,7 +798,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, tmp = PyUnicode_FromOrdinal(x); inumeric_chars = 0; n_digits = 1; - maxchar = Py_MAX(maxchar, x); + maxchar = Py_MAX(maxchar, (Py_UCS4)x); /* As a sort-of hack, we tell calc_number_widths that we only have "remainder" characters. calc_number_widths thinks -- cgit v1.2.1 From c6d22e93db4b5e0cdb94ae023a4b7e43693dfed2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 26 Jan 2012 00:31:49 +0100 Subject: Remove now useless arbitrary limit of module name length --- Python/import.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'Python') diff --git a/Python/import.c b/Python/import.c index d5b89d5966..8bd7a61722 100644 --- a/Python/import.c +++ b/Python/import.c @@ -2052,12 +2052,6 @@ find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list, if (p_loader != NULL) *p_loader = NULL; - if (PyUnicode_GET_LENGTH(name) > MAXPATHLEN) { - PyErr_SetString(PyExc_OverflowError, - "module name is too long"); - return NULL; - } - /* sys.meta_path import hook */ if (p_loader != NULL) { _Py_IDENTIFIER(find_module); -- cgit v1.2.1 From 3e0ad1e1013b0ceefe9b761cbe21d5e9511dfeb5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 1 Feb 2012 00:22:23 +0100 Subject: Issue #13706: Add assertions to detect bugs earlier --- Python/formatter_unicode.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index eee99134ad..ed716a5b97 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -559,8 +559,9 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, Py_ssize_t t; for (t = 0; t < spec->n_prefix; t++) { Py_UCS4 c = PyUnicode_READ(kind, data, pos + t); + c = Py_TOUPPER(c); assert (c <= 127); - PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c)); + PyUnicode_WRITE(kind, data, pos + t, c); } } pos += spec->n_prefix; @@ -603,11 +604,12 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, Py_ssize_t t; for (t = 0; t < spec->n_grouped_digits; t++) { Py_UCS4 c = PyUnicode_READ(kind, data, pos + t); + c = Py_TOUPPER(c); if (c > 127) { PyErr_SetString(PyExc_SystemError, "non-ascii grouped digit"); return -1; } - PyUnicode_WRITE(kind, data, pos + t, Py_TOUPPER(c)); + PyUnicode_WRITE(kind, data, pos + t, c); } } pos += spec->n_grouped_digits; @@ -733,6 +735,7 @@ format_string_internal(PyObject *value, const InternalFormatSpec *format) Py_CLEAR(result); done: + assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -759,7 +762,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, produces non-digits */ Py_ssize_t n_prefix = 0; /* Count of prefix chars, (e.g., '0x') */ Py_ssize_t n_total; - Py_ssize_t prefix; + Py_ssize_t prefix = 0; NumberFieldWidths spec; long x; int err; @@ -894,6 +897,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, done: Py_XDECREF(tmp); + assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -1036,6 +1040,7 @@ format_float_internal(PyObject *value, done: PyMem_Free(buf); Py_DECREF(unicode_tmp); + assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -1270,6 +1275,7 @@ done: PyMem_Free(im_buf); Py_XDECREF(re_unicode_tmp); Py_XDECREF(im_unicode_tmp); + assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } -- cgit v1.2.1 From 23a8cad783fc1e7e418a79d1e8a8822d8f4a6225 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 7 Feb 2012 23:41:01 +0100 Subject: Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime() to have a resolution of 100 ns instead of 1 ms (the clock accuracy is between 0.5 ms and 15 ms). --- Python/pytime.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'Python') diff --git a/Python/pytime.c b/Python/pytime.c index 6fb7695911..bec1c713e6 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -1,7 +1,9 @@ #include "Python.h" +#ifdef MS_WINDOWS +#include +#endif -#ifdef __APPLE__ -#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) +#if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) /* * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter * might fail on some platforms. This fallback is unwanted on MacOSX because @@ -10,18 +12,30 @@ */ # undef HAVE_FTIME #endif -#endif -#ifdef HAVE_FTIME +#if defined(HAVE_FTIME) && !defined(MS_WINDOWS) #include -#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) extern int ftime(struct timeb *); -#endif /* MS_WINDOWS */ -#endif /* HAVE_FTIME */ +#endif void _PyTime_gettimeofday(_PyTime_timeval *tp) { +#ifdef MS_WINDOWS + FILETIME system_time; + ULARGE_INTEGER large; + ULONGLONG microseconds; + + GetSystemTimeAsFileTime(&system_time); + large.u.LowPart = system_time.dwLowDateTime; + large.u.HighPart = system_time.dwHighDateTime; + /* 11,644,473,600,000,000: number of microseconds between + the 1st january 1601 and the 1st january 1970 (369 years + 89 leap + days). */ + microseconds = large.QuadPart / 10 - 11644473600000000; + tp->tv_sec = microseconds / 1000000; + tp->tv_usec = microseconds % 1000000; +#else /* There are three ways to get the time: (1) gettimeofday() -- resolution in microseconds (2) ftime() -- resolution in milliseconds @@ -30,6 +44,7 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may fail, so we fall back on ftime() or time(). Note: clock resolution does not imply clock accuracy! */ + #ifdef HAVE_GETTIMEOFDAY #ifdef GETTIMEOFDAY_NO_TZ if (gettimeofday(tp) == 0) @@ -39,6 +54,7 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) return; #endif /* !GETTIMEOFDAY_NO_TZ */ #endif /* !HAVE_GETTIMEOFDAY */ + #if defined(HAVE_FTIME) { struct timeb t; @@ -50,7 +66,8 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) tp->tv_sec = time(NULL); tp->tv_usec = 0; #endif /* !HAVE_FTIME */ - return; + +#endif /* MS_WINDOWS */ } void -- cgit v1.2.1 From 84a9491874cb99e24227206345f5a4b6060e27c8 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Mon, 20 Feb 2012 19:41:11 +0100 Subject: Issue #14040: Remove rarely used file name suffixes for C extensions (under POSIX mainly). This will improve import performance a bit (especially under importlib). --- Python/dynload_aix.c | 1 - Python/dynload_dl.c | 1 - Python/dynload_hpux.c | 1 - Python/dynload_next.c | 1 - Python/dynload_shlib.c | 6 ------ 5 files changed, 10 deletions(-) (limited to 'Python') diff --git a/Python/dynload_aix.c b/Python/dynload_aix.c index 6287c86edf..8346f065e3 100644 --- a/Python/dynload_aix.c +++ b/Python/dynload_aix.c @@ -28,7 +28,6 @@ typedef struct Module { const struct filedescr _PyImport_DynLoadFiletab[] = { {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, {0, 0} }; diff --git a/Python/dynload_dl.c b/Python/dynload_dl.c index 37519b23e7..a914a0846e 100644 --- a/Python/dynload_dl.c +++ b/Python/dynload_dl.c @@ -11,7 +11,6 @@ extern char *Py_GetProgramName(void); const struct filedescr _PyImport_DynLoadFiletab[] = { {".o", "rb", C_EXTENSION}, - {"module.o", "rb", C_EXTENSION}, {0, 0} }; diff --git a/Python/dynload_hpux.c b/Python/dynload_hpux.c index 3ebbbad01f..1004010902 100644 --- a/Python/dynload_hpux.c +++ b/Python/dynload_hpux.c @@ -15,7 +15,6 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {SHLIB_EXT, "rb", C_EXTENSION}, - {"module"SHLIB_EXT, "rb", C_EXTENSION}, {0, 0} }; diff --git a/Python/dynload_next.c b/Python/dynload_next.c index eb17950b45..5caff8bc9c 100644 --- a/Python/dynload_next.c +++ b/Python/dynload_next.c @@ -10,7 +10,6 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, {0, 0} }; diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 1c215c329c..ab24238f57 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -39,7 +39,6 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __CYGWIN__ {".dll", "rb", C_EXTENSION}, - {"module.dll", "rb", C_EXTENSION}, #else /* !__CYGWIN__ */ #if defined(PYOS_OS2) && defined(PYCC_GCC) {".pyd", "rb", C_EXTENSION}, @@ -48,15 +47,10 @@ const struct filedescr _PyImport_DynLoadFiletab[] = { #ifdef __VMS {".exe", "rb", C_EXTENSION}, {".EXE", "rb", C_EXTENSION}, - {"module.exe", "rb", C_EXTENSION}, - {"MODULE.EXE", "rb", C_EXTENSION}, #else /* !__VMS */ {"." SOABI ".so", "rb", C_EXTENSION}, - {"module." SOABI ".so", "rb", C_EXTENSION}, {".abi" PYTHON_ABI_STRING ".so", "rb", C_EXTENSION}, - {"module.abi" PYTHON_ABI_STRING ".so", "rb", C_EXTENSION}, {".so", "rb", C_EXTENSION}, - {"module.so", "rb", C_EXTENSION}, #endif /* __VMS */ #endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */ #endif /* __CYGWIN__ */ -- cgit v1.2.1 From baf692feaf7fca5fe407b4d0133981b6245759c2 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 21 Feb 2012 16:08:05 -0500 Subject: enable hash randomization by default --- Python/random.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'Python') diff --git a/Python/random.c b/Python/random.c index a2ae002261..7019a3503e 100644 --- a/Python/random.c +++ b/Python/random.c @@ -256,17 +256,6 @@ _PyRandom_Init(void) return; _Py_HashSecret_Initialized = 1; - /* - By default, hash randomization is disabled, and only - enabled if PYTHONHASHSEED is set to non-empty or if - "-R" is provided at the command line: - */ - if (!Py_HashRandomizationFlag) { - /* Disable the randomized hash: */ - memset(secret, 0, secret_size); - return; - } - /* Hash randomization is enabled. Generate a per-process secret, using PYTHONHASHSEED if provided. -- cgit v1.2.1 From 9e8e9c35e7a50d4fadb0898b3a09ae9029f04239 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 24 Feb 2012 00:37:51 +0100 Subject: Issue #13706: Fix format(int, "n") for locale with non-ASCII thousands separator * Decode thousands separator and decimal point using PyUnicode_DecodeLocale() (from the locale encoding), instead of decoding them implicitly from latin1 * Remove _PyUnicode_InsertThousandsGroupingLocale(), it was not used * Change _PyUnicode_InsertThousandsGrouping() API to return the maximum character if unicode is NULL * Replace MIN/MAX macros by Py_MIN/Py_MAX * stringlib/undef.h undefines STRINGLIB_IS_UNICODE * stringlib/localeutil.h only supports Unicode --- Python/formatter_unicode.c | 142 ++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 53 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index ed716a5b97..94f8047e18 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -346,11 +346,13 @@ fill_padding(PyObject *s, Py_ssize_t start, Py_ssize_t nchars, before and including the decimal. Note that locales only support 8-bit chars, not unicode. */ typedef struct { - char *decimal_point; - char *thousands_sep; - char *grouping; + PyObject *decimal_point; + PyObject *thousands_sep; + const char *grouping; } LocaleInfo; +#define STATIC_LOCALE_INFO_INIT {0, 0, 0} + /* describes the layout for an integer, see the comment in calc_number_widths() for details */ typedef struct { @@ -415,7 +417,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, Py_UCS4 sign_char, PyObject *number, Py_ssize_t n_start, Py_ssize_t n_end, Py_ssize_t n_remainder, int has_decimal, const LocaleInfo *locale, - const InternalFormatSpec *format) + const InternalFormatSpec *format, Py_UCS4 *maxchar) { Py_ssize_t n_non_digit_non_padding; Py_ssize_t n_padding; @@ -423,7 +425,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, spec->n_digits = n_end - n_start - n_remainder - (has_decimal?1:0); spec->n_lpadding = 0; spec->n_prefix = n_prefix; - spec->n_decimal = has_decimal ? strlen(locale->decimal_point) : 0; + spec->n_decimal = has_decimal ? PyUnicode_GET_LENGTH(locale->decimal_point) : 0; spec->n_remainder = n_remainder; spec->n_spadding = 0; spec->n_rpadding = 0; @@ -484,11 +486,15 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, to special case it because the grouping code always wants to have at least one character. */ spec->n_grouped_digits = 0; - else + else { + Py_UCS4 grouping_maxchar; spec->n_grouped_digits = _PyUnicode_InsertThousandsGrouping( - NULL, PyUnicode_1BYTE_KIND, NULL, 0, NULL, + NULL, 0, + 0, NULL, spec->n_digits, spec->n_min_width, - locale->grouping, locale->thousands_sep); + locale->grouping, locale->thousands_sep, &grouping_maxchar); + *maxchar = Py_MAX(*maxchar, grouping_maxchar); + } /* Given the desired width and the total of digit and non-digit space we consume, see if we need any padding. format->width can @@ -519,6 +525,10 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, break; } } + + if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding) + *maxchar = Py_MAX(*maxchar, format->fill_char); + return spec->n_lpadding + spec->n_sign + spec->n_prefix + spec->n_spadding + spec->n_grouped_digits + spec->n_decimal + spec->n_remainder + spec->n_rpadding; @@ -587,12 +597,11 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, r = #endif _PyUnicode_InsertThousandsGrouping( - out, kind, - (char*)data + kind * pos, + out, pos, spec->n_grouped_digits, pdigits + kind * d_pos, spec->n_digits, spec->n_min_width, - locale->grouping, locale->thousands_sep); + locale->grouping, locale->thousands_sep, NULL); #ifndef NDEBUG assert(r == spec->n_grouped_digits); #endif @@ -615,10 +624,8 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, pos += spec->n_grouped_digits; if (spec->n_decimal) { - Py_ssize_t t; - for (t = 0; t < spec->n_decimal; ++t) - PyUnicode_WRITE(kind, data, pos + t, - locale->decimal_point[t]); + if (PyUnicode_CopyCharacters(out, pos, locale->decimal_point, 0, spec->n_decimal) < 0) + return -1; pos += spec->n_decimal; d_pos += 1; } @@ -643,32 +650,60 @@ static char no_grouping[1] = {CHAR_MAX}; grouping description, either for the current locale if type is LT_CURRENT_LOCALE, a hard-coded locale if LT_DEFAULT_LOCALE, or none if LT_NO_LOCALE. */ -static void +static int get_locale_info(int type, LocaleInfo *locale_info) { switch (type) { case LT_CURRENT_LOCALE: { struct lconv *locale_data = localeconv(); - locale_info->decimal_point = locale_data->decimal_point; - locale_info->thousands_sep = locale_data->thousands_sep; + locale_info->decimal_point = PyUnicode_DecodeLocale( + locale_data->decimal_point, + NULL); + if (locale_info->decimal_point == NULL) + return -1; + locale_info->thousands_sep = PyUnicode_DecodeLocale( + locale_data->thousands_sep, + NULL); + if (locale_info->thousands_sep == NULL) { + Py_DECREF(locale_info->decimal_point); + return -1; + } locale_info->grouping = locale_data->grouping; break; } case LT_DEFAULT_LOCALE: - locale_info->decimal_point = "."; - locale_info->thousands_sep = ","; + locale_info->decimal_point = PyUnicode_FromOrdinal('.'); + locale_info->thousands_sep = PyUnicode_FromOrdinal(','); + if (!locale_info->decimal_point || !locale_info->thousands_sep) { + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); + return -1; + } locale_info->grouping = "\3"; /* Group every 3 characters. The (implicit) trailing 0 means repeat infinitely. */ break; case LT_NO_LOCALE: - locale_info->decimal_point = "."; - locale_info->thousands_sep = ""; + locale_info->decimal_point = PyUnicode_FromOrdinal('.'); + locale_info->thousands_sep = PyUnicode_New(0, 0); + if (!locale_info->decimal_point || !locale_info->thousands_sep) { + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); + return -1; + } locale_info->grouping = no_grouping; break; default: assert(0); } + return 0; +} + +static void +free_locale_info(LocaleInfo *locale_info) +{ + Py_XDECREF(locale_info->decimal_point); + Py_XDECREF(locale_info->thousands_sep); } /************************************************************************/ @@ -769,7 +804,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; /* no precision allowed on integers */ if (format->precision != -1) { @@ -868,18 +903,17 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, } /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Calculate how much memory we'll need. */ n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars, - inumeric_chars + n_digits, n_remainder, 0, &locale, format); - - if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) - maxchar = Py_MAX(maxchar, format->fill_char); + inumeric_chars + n_digits, n_remainder, 0, + &locale, format, &maxchar); /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); @@ -897,6 +931,7 @@ format_int_or_long_internal(PyObject *value, const InternalFormatSpec *format, done: Py_XDECREF(tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -938,7 +973,7 @@ format_float_internal(PyObject *value, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; if (format->alternate) flags |= Py_DTSF_ALT; @@ -1009,19 +1044,17 @@ format_float_internal(PyObject *value, parse_number(unicode_tmp, index, index + n_digits, &n_remainder, &has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Calculate how much memory we'll need. */ n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, index + n_digits, n_remainder, has_decimal, - &locale, format); - - if (spec.n_lpadding || spec.n_spadding || spec.n_rpadding) - maxchar = Py_MAX(maxchar, format->fill_char); + &locale, format, &maxchar); /* Allocate the memory. */ result = PyUnicode_New(n_total, maxchar); @@ -1040,6 +1073,7 @@ format_float_internal(PyObject *value, done: PyMem_Free(buf); Py_DECREF(unicode_tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } @@ -1094,7 +1128,7 @@ format_complex_internal(PyObject *value, /* Locale settings, either from the actual locale or from a hard-code pseudo-locale */ - LocaleInfo locale; + LocaleInfo locale = STATIC_LOCALE_INFO_INIT; /* Zero padding is not allowed. */ if (format->fill_char == '0') { @@ -1190,11 +1224,12 @@ format_complex_internal(PyObject *value, &n_im_remainder, &im_has_decimal); /* Determine the grouping, separator, and decimal point, if any. */ - get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : - (format->thousands_separators ? - LT_DEFAULT_LOCALE : - LT_NO_LOCALE), - &locale); + if (get_locale_info(format->type == 'n' ? LT_CURRENT_LOCALE : + (format->thousands_separators ? + LT_DEFAULT_LOCALE : + LT_NO_LOCALE), + &locale) == -1) + goto done; /* Turn off any padding. We'll do it later after we've composed the numbers without padding. */ @@ -1205,7 +1240,8 @@ format_complex_internal(PyObject *value, /* Calculate how much memory we'll need. */ n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, re_unicode_tmp, i_re, i_re + n_re_digits, n_re_remainder, - re_has_decimal, &locale, &tmp_format); + re_has_decimal, &locale, &tmp_format, + &maxchar); /* Same formatting, but always include a sign, unless the real part is * going to be omitted, in which case we use whatever sign convention was @@ -1214,7 +1250,8 @@ format_complex_internal(PyObject *value, tmp_format.sign = '+'; n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, im_unicode_tmp, i_im, i_im + n_im_digits, n_im_remainder, - im_has_decimal, &locale, &tmp_format); + im_has_decimal, &locale, &tmp_format, + &maxchar); if (skip_re) n_re_total = 0; @@ -1223,9 +1260,7 @@ format_complex_internal(PyObject *value, calc_padding(n_re_total + n_im_total + 1 + add_parens * 2, format->width, format->align, &lpad, &rpad, &total); - if (re_spec.n_lpadding || re_spec.n_spadding || re_spec.n_rpadding - || im_spec.n_lpadding || im_spec.n_spadding || im_spec.n_rpadding - || lpad || rpad) + if (lpad || rpad) maxchar = Py_MAX(maxchar, format->fill_char); result = PyUnicode_New(total, maxchar); @@ -1275,6 +1310,7 @@ done: PyMem_Free(im_buf); Py_XDECREF(re_unicode_tmp); Py_XDECREF(im_unicode_tmp); + free_locale_info(&locale); assert(!result || _PyUnicode_CheckConsistency(result, 1)); return result; } -- cgit v1.2.1 From c0cd820dd5983d13501dab01aab1fcf6380a8e0c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 24 Feb 2012 01:44:47 +0100 Subject: Issue #13706: Fix format(float, "n") for locale with non-ASCII decimal point (e.g. ps_aF) --- Python/formatter_unicode.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 94f8047e18..58e66e0d90 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -529,6 +529,9 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, if (spec->n_lpadding || spec->n_spadding || spec->n_rpadding) *maxchar = Py_MAX(*maxchar, format->fill_char); + if (spec->n_decimal) + *maxchar = Py_MAX(*maxchar, PyUnicode_MAX_CHAR_VALUE(locale->decimal_point)); + return spec->n_lpadding + spec->n_sign + spec->n_prefix + spec->n_spadding + spec->n_grouped_digits + spec->n_decimal + spec->n_remainder + spec->n_rpadding; @@ -548,10 +551,7 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, Py_ssize_t d_pos = d_start; unsigned int kind = PyUnicode_KIND(out); void *data = PyUnicode_DATA(out); - -#ifndef NDEBUG Py_ssize_t r; -#endif if (spec->n_lpadding) { PyUnicode_Fill(out, pos, pos + spec->n_lpadding, fill_char); @@ -593,18 +593,15 @@ fill_number(PyObject *out, Py_ssize_t pos, const NumberFieldWidths *spec, if (pdigits == NULL) return -1; } -#ifndef NDEBUG - r = -#endif - _PyUnicode_InsertThousandsGrouping( + r = _PyUnicode_InsertThousandsGrouping( out, pos, spec->n_grouped_digits, pdigits + kind * d_pos, spec->n_digits, spec->n_min_width, locale->grouping, locale->thousands_sep, NULL); -#ifndef NDEBUG + if (r == -1) + return -1; assert(r == spec->n_grouped_digits); -#endif if (PyUnicode_KIND(digits) < kind) PyMem_Free(pdigits); d_pos += spec->n_digits; -- cgit v1.2.1 From fc7f17dd7a77350fd6906e2082f2375647b57c6a Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 26 Feb 2012 17:49:52 +1000 Subject: Close issue #6210: Implement PEP 409 --- Python/ceval.c | 17 +++++++++-------- Python/pythonrun.c | 6 +++++- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 06bff4c169..017dc4aab9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3567,22 +3567,23 @@ do_raise(PyObject *exc, PyObject *cause) if (cause) { PyObject *fixed_cause; + int result; if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto raise_error; - Py_DECREF(cause); - } - else if (PyExceptionInstance_Check(cause)) { + Py_CLEAR(cause); + } else { + /* Let "exc.__cause__ = cause" handle all further checks */ fixed_cause = cause; + cause = NULL; /* Steal the reference */ } - else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); + /* We retain ownership of the reference to fixed_cause */ + result = _PyException_SetCauseChecked(value, fixed_cause); + Py_DECREF(fixed_cause); + if (result < 0) { goto raise_error; } - PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index a642c0b0da..f4e7e7b9b2 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1698,7 +1698,11 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen) else if (PyExceptionInstance_Check(value)) { cause = PyException_GetCause(value); context = PyException_GetContext(value); - if (cause) { + if (cause && cause == Py_None) { + /* print neither cause nor context */ + ; + } + else if (cause) { res = PySet_Contains(seen, cause); if (res == -1) PyErr_Clear(); -- cgit v1.2.1 From dd75ad79434f0b552e1a7f2ee8a0ee20dbfb02ba Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Wed, 29 Feb 2012 18:31:31 -0500 Subject: Issue #14153 Create _Py_device_encoding() to prevent _io from having to import the os module. --- Python/fileutils.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'Python') diff --git a/Python/fileutils.c b/Python/fileutils.c index 8993c8c497..501cb8c8d6 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -3,6 +3,40 @@ # include #endif +#ifdef HAVE_LANGINFO_H +#include +#endif + +PyObject * +_Py_device_encoding(int fd) +{ +#if defined(MS_WINDOWS) || defined(MS_WIN64) + UINT cp; +#endif + if (!_PyVerify_fd(fd) || !isatty(fd)) { + Py_RETURN_NONE; + } +#if defined(MS_WINDOWS) || defined(MS_WIN64) + if (fd == 0) + cp = GetConsoleCP(); + else if (fd == 1 || fd == 2) + cp = GetConsoleOutputCP(); + else + cp = 0; + /* GetConsoleCP() and GetConsoleOutputCP() return 0 if the application + has no console */ + if (cp != 0) + return PyUnicode_FromFormat("cp%u", (unsigned int)cp); +#elif defined(CODESET) + { + char *codeset = nl_langinfo(CODESET); + if (codeset != NULL && codeset[0] != 0) + return PyUnicode_FromString(codeset); + } +#endif + Py_RETURN_NONE; +} + #ifdef HAVE_STAT /* Decode a byte string from the locale encoding with the -- cgit v1.2.1 From dc87ffd3df0f0a831b58372ce6f9307cf5da356b Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 2 Mar 2012 18:22:23 +0100 Subject: Simplify code in marshal.c. --- Python/marshal.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'Python') diff --git a/Python/marshal.c b/Python/marshal.c index 17353b2d58..77824d4129 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -1239,7 +1239,6 @@ PyObject * PyMarshal_WriteObjectToString(PyObject *x, int version) { WFILE wf; - PyObject *res = NULL; wf.fp = NULL; wf.readable = NULL; @@ -1273,12 +1272,7 @@ PyMarshal_WriteObjectToString(PyObject *x, int version) :"object too deeply nested to marshal"); return NULL; } - if (wf.str != NULL) { - /* XXX Quick hack -- need to do this differently */ - res = PyBytes_FromObject(wf.str); - Py_DECREF(wf.str); - } - return res; + return wf.str; } /* And an interface for Python programs... */ -- cgit v1.2.1 From 9444533c014ebfd2aed80f40ce8d15ce5c675a40 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 2 Mar 2012 22:54:03 +0100 Subject: Issue #13964: signal.sigtimedwait() timeout is now a float instead of a tuple Add a private API to convert an int or float to a C timespec structure. --- Python/pytime.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'Python') diff --git a/Python/pytime.c b/Python/pytime.c index bec1c713e6..d23ce75b43 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -70,6 +70,51 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) #endif /* MS_WINDOWS */ } +int +_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +{ + if (PyFloat_Check(obj)) { + double d, intpart, floatpart, err; + + d = PyFloat_AsDouble(obj); + floatpart = modf(d, &intpart); + if (floatpart < 0) { + floatpart = 1.0 + floatpart; + intpart -= 1.0; + } + + *sec = (time_t)intpart; + err = intpart - (double)*sec; + if (err <= -1.0 || err >= 1.0) + goto overflow; + + floatpart *= 1e9; + *nsec = (long)floatpart; + return 0; + } + else { +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + *sec = PyLong_AsLongLong(obj); +#else + assert(sizeof(time_t) <= sizeof(long)); + *sec = PyLong_AsLong(obj); +#endif + if (*sec == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + else + return -1; + } + *nsec = 0; + return 0; + } + +overflow: + PyErr_SetString(PyExc_OverflowError, + "timestamp out of range for platform time_t"); + return -1; +} + void _PyTime_Init() { -- cgit v1.2.1 From 061f185f0d20236b4598c47dbcb5963cfcd7a876 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 4 Mar 2012 12:04:06 +0000 Subject: Basic support for PEP 414 without docs or tests. --- Python/ast.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Python') diff --git a/Python/ast.c b/Python/ast.c index c56564279b..0f93098712 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -3796,6 +3796,9 @@ parsestr(struct compiling *c, const node *n, int *bytesmode) quote = *++s; *bytesmode = 1; } + else if (quote == 'u' || quote == 'U') { + quote = *++s; + } else if (quote == 'r' || quote == 'R') { quote = *++s; rawmode = 1; -- cgit v1.2.1 From d7db95dd1faddb29bc844fc836938c98642579ea Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sun, 4 Mar 2012 16:26:19 +0100 Subject: Update copyright years and version name. --- Python/getcopyright.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getcopyright.c b/Python/getcopyright.c index d1e2578747..d83c6da1a2 100644 --- a/Python/getcopyright.c +++ b/Python/getcopyright.c @@ -19,5 +19,5 @@ All Rights Reserved."; const char * Py_GetCopyright(void) { - return cprt; + return cprt; } -- cgit v1.2.1 From 9e7326a599e76cc4f5bd03e6b3744d4008a01ade Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 12 Mar 2012 09:46:44 -0700 Subject: give the AST class a __dict__ --- Python/Python-ast.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 2603b812f0..cf73beaa15 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -1,5 +1,7 @@ /* File automatically generated by Parser/asdl_c.py. */ +#include + #include "Python.h" #include "Python-ast.h" @@ -453,6 +455,11 @@ static char *withitem_fields[]={ }; +typedef struct { + PyObject_HEAD; + PyObject *dict; +} AST_object; + static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { @@ -531,10 +538,15 @@ static PyMethodDef ast_type_methods[] = { {NULL} }; +static PyGetSetDef ast_type_getsets[] = { + {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, + {NULL} +}; + static PyTypeObject AST_type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "_ast.AST", - sizeof(PyObject), + sizeof(AST_object), 0, 0, /* tp_dealloc */ 0, /* tp_print */ @@ -561,12 +573,12 @@ static PyTypeObject AST_type = { 0, /* tp_iternext */ ast_type_methods, /* tp_methods */ 0, /* tp_members */ - 0, /* tp_getset */ + ast_type_getsets, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof(AST_object, dict),/* tp_dictoffset */ (initproc)ast_type_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ -- cgit v1.2.1 From d5bb8362e9a919dab6fd05eba0731a3db3a5063f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 01:17:31 +0100 Subject: Try to fix compilation of Python-ast.c on Visual Studio 2008 --- Python/Python-ast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index cf73beaa15..1178d74d7f 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -456,7 +456,7 @@ static char *withitem_fields[]={ typedef struct { - PyObject_HEAD; + PyObject_HEAD PyObject *dict; } AST_object; -- cgit v1.2.1 From adce5ff128974a4206a25388f449633c579d4e8a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 13:35:55 +0100 Subject: Close #14180: Factorize code to convert a number of seconds to time_t, timeval or timespec time.ctime(), gmtime(), time.localtime(), datetime.date.fromtimestamp(), datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now raises an OverflowError, instead of a ValueError, if the timestamp does not fit in time_t. datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now round microseconds towards zero instead of rounding to nearest with ties going away from zero. --- Python/pytime.c | 99 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 22 deletions(-) (limited to 'Python') diff --git a/Python/pytime.c b/Python/pytime.c index d23ce75b43..79a1a33616 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -70,9 +70,37 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) #endif /* MS_WINDOWS */ } -int -_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +static void +error_time_t_overflow(void) +{ + PyErr_SetString(PyExc_OverflowError, + "timestamp out of range for platform time_t"); +} + +static time_t +_PyLong_AsTime_t(PyObject *obj) +{ +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + PY_LONG_LONG val; + val = PyLong_AsLongLong(obj); +#else + long val; + assert(sizeof(time_t) <= sizeof(long)); + val = PyLong_AsLong(obj); +#endif + if (val == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + error_time_t_overflow(); + return -1; + } + return (time_t)val; +} + +static int +_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, + double denominator) { + assert(denominator <= LONG_MAX); if (PyFloat_Check(obj)) { double d, intpart, floatpart, err; @@ -85,34 +113,61 @@ _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) *sec = (time_t)intpart; err = intpart - (double)*sec; - if (err <= -1.0 || err >= 1.0) - goto overflow; + if (err <= -1.0 || err >= 1.0) { + error_time_t_overflow(); + return -1; + } - floatpart *= 1e9; - *nsec = (long)floatpart; + floatpart *= denominator; + *numerator = (long)floatpart; return 0; } else { -#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG - *sec = PyLong_AsLongLong(obj); -#else - assert(sizeof(time_t) <= sizeof(long)); - *sec = PyLong_AsLong(obj); -#endif - if (*sec == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - else - return -1; + *sec = _PyLong_AsTime_t(obj); + if (*sec == (time_t)-1 && PyErr_Occurred()) + return -1; + *numerator = 0; + return 0; + } +} + +int +_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec) +{ + if (PyFloat_Check(obj)) { + double d, intpart, err; + + /*whent = _PyTime_DoubleToTimet(d);*/ + + d = PyFloat_AsDouble(obj); + (void)modf(d, &intpart); + + *sec = (time_t)intpart; + err = intpart - (double)*sec; + if (err <= -1.0 || err >= 1.0) { + error_time_t_overflow(); + return -1; } - *nsec = 0; return 0; } + else { + *sec = _PyLong_AsTime_t(obj); + if (*sec == (time_t)-1 && PyErr_Occurred()) + return -1; + return 0; + } +} -overflow: - PyErr_SetString(PyExc_OverflowError, - "timestamp out of range for platform time_t"); - return -1; +int +_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +{ + return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9); +} + +int +_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec) +{ + return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6); } void -- cgit v1.2.1 From 08a3385bd19cd7a0ac32758f3f24fbdd49ad4fda Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 13:50:34 +0100 Subject: Issue #14180: Remove commented code --- Python/pytime.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python') diff --git a/Python/pytime.c b/Python/pytime.c index 79a1a33616..75d80e2576 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -137,8 +137,6 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec) if (PyFloat_Check(obj)) { double d, intpart, err; - /*whent = _PyTime_DoubleToTimet(d);*/ - d = PyFloat_AsDouble(obj); (void)modf(d, &intpart); -- cgit v1.2.1 From 75ff7e8c4aa9633a8c87788c24ab8335fa1dd698 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 19:12:23 +0100 Subject: Issue #14180: Fix an invalid rounding when compiler optimization are enabled Use volatile keyword to disable localy unsafe float optimizations. --- Python/pytime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/pytime.c b/Python/pytime.c index 75d80e2576..e7dadc7605 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -102,7 +102,9 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, { assert(denominator <= LONG_MAX); if (PyFloat_Check(obj)) { - double d, intpart, floatpart, err; + double d, intpart, err; + /* volatile avoids unsafe optimization on float enabled by gcc -O3 */ + volatile double floatpart; d = PyFloat_AsDouble(obj); floatpart = modf(d, &intpart); -- cgit v1.2.1 From feb250da193d7840bcf341f8e1630dd70afde01d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 14 Mar 2012 21:50:29 -0500 Subject: free AST's dict --- Python/Python-ast.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 1178d74d7f..d9e13e28b0 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -460,6 +460,12 @@ typedef struct { PyObject *dict; } AST_object; +static void +ast_dealloc(AST_object *self) +{ + Py_CLEAR(self->dict); +} + static int ast_type_init(PyObject *self, PyObject *args, PyObject *kw) { @@ -548,7 +554,7 @@ static PyTypeObject AST_type = { "_ast.AST", sizeof(AST_object), 0, - 0, /* tp_dealloc */ + (destructor)ast_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ -- cgit v1.2.1 From 0ea564cff248528b899a26f75b173f35b55d505a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 15 Mar 2012 15:37:39 -0500 Subject: perform yield from delegation by repeating YIELD_FROM opcode (closes #14230) This allows generators that are using yield from to be seen by debuggers. It also kills the f_yieldfrom field on frame objects. Patch mostly from Mark Shannon with a few tweaks by me. --- Python/ceval.c | 58 ++++++++++++++++++++++---------------------------------- Python/compile.c | 6 ++++-- Python/import.c | 3 ++- 3 files changed, 29 insertions(+), 38 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 017dc4aab9..54980565bf 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1170,6 +1170,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) f->f_lasti to -1 (i.e. the index *before* the first instruction) and YIELD_VALUE doesn't fiddle with f_lasti any more. So this does work. Promise. + YIELD_FROM sets f_lasti to itself, in order to repeated yield + multiple values. When the PREDICT() macros are enabled, some opcode pairs follow in direct succession without updating f->f_lasti. A successful @@ -1830,49 +1832,35 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(YIELD_FROM) u = POP(); - x = PyObject_GetIter(u); + x = TOP(); + /* send u to x */ + if (PyGen_CheckExact(x)) { + retval = _PyGen_Send((PyGenObject *)x, u); + } else { + if (u == Py_None) + retval = PyIter_Next(x); + else + retval = PyObject_CallMethod(x, "send", "O", u); + } Py_DECREF(u); - if (x == NULL) - break; - /* x is now the iterator, make the first next() call */ - retval = (*Py_TYPE(x)->tp_iternext)(x); if (!retval) { - PyObject *et, *ev, *tb; - /* iter may be exhausted */ - Py_CLEAR(x); - if (PyErr_Occurred() && - !PyErr_ExceptionMatches(PyExc_StopIteration)) { - /* some other exception */ + PyObject *val; + x = POP(); /* Remove iter from stack */ + Py_DECREF(x); + err = PyGen_FetchStopIterationValue(&val); + if (err < 0) { + x = NULL; break; } - /* try to get return value from exception */ - PyErr_Fetch(&et, &ev, &tb); - Py_XDECREF(et); - Py_XDECREF(tb); - /* u is return value */ - u = NULL; - if (ev) { - u = PyObject_GetAttrString(ev, "value"); - Py_DECREF(ev); - if (u == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - /* some other exception */ - break; - } - PyErr_Clear(); - } - } - if (u == NULL) { - u = Py_None; - Py_INCREF(u); - } - PUSH(u); + x = val; + PUSH(x); continue; } - /* x is iterator, retval is value to be yielded */ - f->f_yieldfrom = x; + /* x remains on stack, retval is value to be yielded */ f->f_stacktop = stack_pointer; why = WHY_YIELD; + /* and repeat... */ + f->f_lasti--; goto fast_yield; TARGET(YIELD_VALUE) diff --git a/Python/compile.c b/Python/compile.c index b64c800e19..1722a5f97d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -840,9 +840,9 @@ opcode_stack_effect(int opcode, int oparg) case IMPORT_STAR: return -1; case YIELD_VALUE: - case YIELD_FROM: return 0; - + case YIELD_FROM: + return -1; case POP_BLOCK: return 0; case POP_EXCEPT: @@ -3323,6 +3323,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e) ADDOP_O(c, LOAD_CONST, Py_None, consts); } if (e->kind == YieldFrom_kind) { + ADDOP(c, GET_ITER); + ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, YIELD_FROM); } else { diff --git a/Python/import.c b/Python/import.c index 4871b99a93..14148c7a1c 100644 --- a/Python/import.c +++ b/Python/import.c @@ -104,7 +104,8 @@ typedef unsigned short mode_t; Python 3.2a2 3180 (add DELETE_DEREF) Python 3.3a0 3190 __class__ super closure changed Python 3.3a0 3200 (__qualname__ added) - 3210 (added size modulo 2**32 to the pyc header) + Python 3.3a1 3210 (added size modulo 2**32 to the pyc header) + 3220 (changed PEP 380 implementation) */ /* MAGIC must change whenever the bytecode emitted by the compiler may no -- cgit v1.2.1 From 06b08c0eb2d160a859326db57c12ea099d74a13c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 15 Mar 2012 15:40:37 -0500 Subject: fix comment --- 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 14148c7a1c..c0f89aaa1b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -104,8 +104,8 @@ typedef unsigned short mode_t; Python 3.2a2 3180 (add DELETE_DEREF) Python 3.3a0 3190 __class__ super closure changed Python 3.3a0 3200 (__qualname__ added) - Python 3.3a1 3210 (added size modulo 2**32 to the pyc header) - 3220 (changed PEP 380 implementation) + 3210 (added size modulo 2**32 to the pyc header) + Python 3.3a1 3220 (changed PEP 380 implementation) */ /* MAGIC must change whenever the bytecode emitted by the compiler may no -- cgit v1.2.1 From c1da75edd489027b5dedb45660466a0b4d8d7063 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Fri, 16 Mar 2012 08:51:42 -0400 Subject: Issue #14325: Stop using python lists, capsules, and the garbage collector to deal with PyArg_Parse* cleanup. --- Python/getargs.c | 205 +++++++++++++++++++++++-------------------------------- 1 file changed, 85 insertions(+), 120 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 77f27bebc9..37f1898819 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -33,16 +33,33 @@ PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, #define FLAG_COMPAT 1 #define FLAG_SIZE_T 2 +typedef int (*destr_t)(PyObject *, void *); + + +/* Keep track of "objects" that have been allocated or initialized and + which will need to be deallocated or cleaned up somehow if overall + parsing fails. +*/ +typedef struct { + void *item; + destr_t destructor; +} freelistentry_t; + +typedef struct { + int first_available; + freelistentry_t *entries; +} freelist_t; + /* Forward */ static int vgetargs1(PyObject *, const char *, va_list *, int); static void seterror(int, const char *, int *, const char *, const char *); static char *convertitem(PyObject *, const char **, va_list *, int, int *, - char *, size_t, PyObject **); + char *, size_t, freelist_t *); static char *converttuple(PyObject *, const char **, va_list *, int, - int *, char *, size_t, int, PyObject **); + int *, char *, size_t, int, freelist_t *); static char *convertsimple(PyObject *, const char **, va_list *, int, char *, - size_t, PyObject **); + size_t, freelist_t *); static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int getbuffer(PyObject *, Py_buffer *, char**); @@ -127,111 +144,54 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) #define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer" #define GETARGS_CAPSULE_NAME_CLEANUP_CONVERT "getargs.cleanup_convert" -static void -cleanup_ptr(PyObject *self) +static int +cleanup_ptr(PyObject *self, void *ptr) { - void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); if (ptr) { PyMem_FREE(ptr); } + return 0; } -static void -cleanup_buffer(PyObject *self) +static int +cleanup_buffer(PyObject *self, void *ptr) { - Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); - if (ptr) { - PyBuffer_Release(ptr); + Py_buffer *buf = (Py_buffer *)ptr; + if (buf) { + PyBuffer_Release(buf); } + return 0; } static int -addcleanup(void *ptr, PyObject **freelist, int is_buffer) +addcleanup(void *ptr, freelist_t *freelist, destr_t destructor) { - PyObject *cobj; - const char *name; - PyCapsule_Destructor destr; - - if (is_buffer) { - destr = cleanup_buffer; - name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; - } else { - destr = cleanup_ptr; - name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; - } - - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - destr(ptr); - return -1; - } - } + int index; - cobj = PyCapsule_New(ptr, name, destr); - if (!cobj) { - destr(ptr); - return -1; - } - if (PyList_Append(*freelist, cobj)) { - Py_DECREF(cobj); - return -1; - } - Py_DECREF(cobj); - return 0; -} + index = freelist->first_available; + freelist->first_available += 1; -static void -cleanup_convert(PyObject *self) -{ - typedef int (*destr_t)(PyObject *, void *); - destr_t destr = (destr_t)PyCapsule_GetContext(self); - void *ptr = PyCapsule_GetPointer(self, - GETARGS_CAPSULE_NAME_CLEANUP_CONVERT); - if (ptr && destr) - destr(NULL, ptr); -} + freelist->entries[index].item = ptr; + freelist->entries[index].destructor = destructor; -static int -addcleanup_convert(void *ptr, PyObject **freelist, int (*destr)(PyObject*,void*)) -{ - PyObject *cobj; - if (!*freelist) { - *freelist = PyList_New(0); - if (!*freelist) { - destr(NULL, ptr); - return -1; - } - } - cobj = PyCapsule_New(ptr, GETARGS_CAPSULE_NAME_CLEANUP_CONVERT, - cleanup_convert); - if (!cobj) { - destr(NULL, ptr); - return -1; - } - if (PyCapsule_SetContext(cobj, destr) == -1) { - /* This really should not happen. */ - Py_FatalError("capsule refused setting of context."); - } - if (PyList_Append(*freelist, cobj)) { - Py_DECREF(cobj); /* This will also call destr. */ - return -1; - } - Py_DECREF(cobj); return 0; } static int -cleanreturn(int retval, PyObject *freelist) +cleanreturn(int retval, freelist_t *freelist) { - if (freelist && retval != 0) { - /* We were successful, reset the destructors so that they - don't get called. */ - Py_ssize_t len = PyList_GET_SIZE(freelist), i; - for (i = 0; i < len; i++) - PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL); - } - Py_XDECREF(freelist); + int index; + + if (retval == 0) { + /* A failure occurred, therefore execute all of the cleanup + functions. + */ + for (index = 0; index < freelist->first_available; ++index) { + freelist->entries[index].destructor(NULL, + freelist->entries[index].item); + } + } + PyMem_Free(freelist->entries); return retval; } @@ -250,7 +210,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) const char *formatsave = format; Py_ssize_t i, len; char *msg; - PyObject *freelist = NULL; + freelist_t freelist = {0, NULL}; int compat = flags & FLAG_COMPAT; assert(compat || (args != (PyObject*)NULL)); @@ -306,6 +266,8 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) format = formatsave; + freelist.entries = PyMem_New(freelistentry_t, max); + if (compat) { if (max == 0) { if (args == NULL) @@ -314,7 +276,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) "%.200s%s takes no arguments", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); - return 0; + return cleanreturn(0, &freelist); } else if (min == 1 && max == 1) { if (args == NULL) { @@ -322,26 +284,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) "%.200s%s takes at least one argument", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); - return 0; + return cleanreturn(0, &freelist); } msg = convertitem(args, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg == NULL) - return cleanreturn(1, freelist); + return cleanreturn(1, &freelist); seterror(levels[0], msg, levels+1, fname, message); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } else { PyErr_SetString(PyExc_SystemError, "old style getargs format uses new features"); - return 0; + return cleanreturn(0, &freelist); } } if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_SystemError, "new style getargs format but argument is not a tuple"); - return 0; + return cleanreturn(0, &freelist); } len = PyTuple_GET_SIZE(args); @@ -359,7 +321,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); else PyErr_SetString(PyExc_TypeError, message); - return 0; + return cleanreturn(0, &freelist); } for (i = 0; i < len; i++) { @@ -370,7 +332,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) sizeof(msgbuf), &freelist); if (msg) { seterror(i+1, msg, levels, fname, msg); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } } @@ -379,10 +341,10 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) *format != '|' && *format != ':' && *format != ';') { PyErr_Format(PyExc_SystemError, "bad format string: %.200s", formatsave); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } - return cleanreturn(1, freelist); + return cleanreturn(1, &freelist); } @@ -446,7 +408,7 @@ seterror(int iarg, const char *msg, int *levels, const char *fname, static char * converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, int toplevel, - PyObject **freelist) + freelist_t *freelist) { int level = 0; int n = 0; @@ -521,7 +483,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, static char * convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) + int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist) { char *msg; const char *format = *p_format; @@ -586,7 +548,7 @@ float_argument_error(PyObject *arg) static char * convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - char *msgbuf, size_t bufsize, PyObject **freelist) + char *msgbuf, size_t bufsize, freelist_t *freelist) { /* For # codes */ #define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ @@ -863,7 +825,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); format++; - if (addcleanup(p, freelist, 1)) { + if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -908,7 +870,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } - if (addcleanup(p, freelist, 1)) { + if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -1120,7 +1082,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, 0)) { + if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr( "(cleanup problem)", @@ -1162,7 +1124,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyErr_NoMemory(); RETURN_ERR_OCCURRED; } - if (addcleanup(*buffer, freelist, 0)) { + if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); @@ -1223,7 +1185,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr("(unspecified)", arg, msgbuf, bufsize); if (res == Py_CLEANUP_SUPPORTED && - addcleanup_convert(addr, freelist, convert) == -1) + addcleanup(addr, freelist, convert) == -1) return converterr("(cleanup problem)", arg, msgbuf, bufsize); } @@ -1254,7 +1216,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyBuffer_Release((Py_buffer*)p); return converterr("contiguous buffer", arg, msgbuf, bufsize); } - if (addcleanup(p, freelist, 1)) { + if (addcleanup(p, freelist, cleanup_buffer)) { return converterr( "(cleanup problem)", arg, msgbuf, bufsize); @@ -1442,7 +1404,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, const char *fname, *msg, *custom_msg, *keyword; int min = INT_MAX; int i, len, nargs, nkeywords; - PyObject *freelist = NULL, *current_arg; + PyObject *current_arg; + freelist_t freelist = {0, NULL}; assert(args != NULL && PyTuple_Check(args)); assert(keywords == NULL || PyDict_Check(keywords)); @@ -1466,6 +1429,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, for (len=0; kwlist[len]; len++) continue; + freelist.entries = PyMem_New(freelistentry_t, len); + nargs = PyTuple_GET_SIZE(args); nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); if (nargs + nkeywords > len) { @@ -1490,7 +1455,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, PyErr_Format(PyExc_RuntimeError, "More keyword list entries (%d) than " "format specifiers (%d)", len, i); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } current_arg = NULL; if (nkeywords) { @@ -1504,11 +1469,11 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, "Argument given by name ('%s') " "and position (%d)", keyword, i+1); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } } else if (nkeywords && PyErr_Occurred()) - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); else if (i < nargs) current_arg = PyTuple_GET_ITEM(args, i); @@ -1517,7 +1482,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { seterror(i+1, msg, levels, fname, custom_msg); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } continue; } @@ -1526,14 +1491,14 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, PyErr_Format(PyExc_TypeError, "Required argument " "'%s' (pos %d) not found", keyword, i+1); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } /* current code reports success when all required args * fulfilled and no keyword args left, with no further * validation. XXX Maybe skip this in debug build ? */ if (!nkeywords) - return cleanreturn(1, freelist); + return cleanreturn(1, &freelist); /* We are into optional args, skip thru to any remaining * keyword args */ @@ -1541,7 +1506,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, if (msg) { PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, format); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } } @@ -1549,7 +1514,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, PyErr_Format(PyExc_RuntimeError, "more argument specifiers than keyword list entries " "(remaining format:'%s')", format); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } /* make sure there are no extraneous keyword arguments */ @@ -1562,7 +1527,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "keywords must be strings"); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } /* check that _PyUnicode_AsString() result is not NULL */ ks = _PyUnicode_AsString(key); @@ -1579,12 +1544,12 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, "'%U' is an invalid keyword " "argument for this function", key); - return cleanreturn(0, freelist); + return cleanreturn(0, &freelist); } } } - return cleanreturn(1, freelist); + return cleanreturn(1, &freelist); } -- cgit v1.2.1 From d8c00dc5e03601e3959e3147dbf9c527e1d3b648 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 16 Mar 2012 09:39:12 -0500 Subject: in 72556ff86828, I should have updated the magic as well as the comment (#14230) --- 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 c0f89aaa1b..144ca71117 100644 --- a/Python/import.c +++ b/Python/import.c @@ -118,7 +118,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 (3210 | ((long)'\r'<<16) | ((long)'\n'<<24)) +#define MAGIC (3220 | ((long)'\r'<<16) | ((long)'\n'<<24)) #define TAG "cpython-" MAJOR MINOR; #define CACHEDIR "__pycache__" /* Current magic word and string tag as globals. */ -- cgit v1.2.1 From 3c4e2b43f9ad635037e3fa7b1f8470998d713afc Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 16 Mar 2012 12:21:02 -0500 Subject: check result of PyMem_New --- Python/getargs.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 37f1898819..268a1134ea 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -267,6 +267,10 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) format = formatsave; freelist.entries = PyMem_New(freelistentry_t, max); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } if (compat) { if (max == 0) { @@ -1430,6 +1434,10 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, continue; freelist.entries = PyMem_New(freelistentry_t, len); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } nargs = PyTuple_GET_SIZE(args); nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); -- cgit v1.2.1 From 6e1127bdc88214b10b93a9a608e127f90eadee2f Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 16 Mar 2012 12:23:39 -0500 Subject: use memory macros --- Python/getargs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 268a1134ea..ba677b49d3 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -191,7 +191,7 @@ cleanreturn(int retval, freelist_t *freelist) freelist->entries[index].item); } } - PyMem_Free(freelist->entries); + PyMem_FREE(freelist->entries); return retval; } @@ -266,7 +266,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) format = formatsave; - freelist.entries = PyMem_New(freelistentry_t, max); + freelist.entries = PyMem_NEW(freelistentry_t, max); if (freelist.entries == NULL) { PyErr_NoMemory(); return 0; @@ -1433,7 +1433,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, for (len=0; kwlist[len]; len++) continue; - freelist.entries = PyMem_New(freelistentry_t, len); + freelist.entries = PyMem_NEW(freelistentry_t, len); if (freelist.entries == NULL) { PyErr_NoMemory(); return 0; -- cgit v1.2.1 From 79d07f6f48cf5c60eb5ef3704aa135613f9bae87 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 16 Mar 2012 12:24:01 -0500 Subject: kill capsule names that we don't need anymore --- Python/getargs.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index ba677b49d3..38eec171d1 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -140,10 +140,6 @@ _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) /* Handle cleanup of allocated memory in case of exception */ -#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr" -#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer" -#define GETARGS_CAPSULE_NAME_CLEANUP_CONVERT "getargs.cleanup_convert" - static int cleanup_ptr(PyObject *self, void *ptr) { -- cgit v1.2.1 From aaecb17871cb7362ca2d54cb6f11b1fce9cacbfd Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 16 Mar 2012 13:25:58 -0500 Subject: plug memory leak (closes #14325) --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 38eec171d1..38c9dde6ff 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1445,7 +1445,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, len, (len == 1) ? "" : "s", nargs + nkeywords); - return 0; + return cleanreturn(0, &freelist); } /* convert tuple args and keyword args in same loop, using kwlist to drive process */ -- cgit v1.2.1 From c067da0e5c050df338fdc2f8ab6a01283f92f0ea Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Tue, 20 Mar 2012 20:06:16 +0000 Subject: Issue #14328: Add keyword-only parameters to PyArg_ParseTupleAndKeywords. They're optional-only for now (unlike in pure Python) but that's all I needed. The syntax can easily be relaxed if we want to support required keyword-only arguments for extension types in the future. --- Python/getargs.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/getargs.c b/Python/getargs.c index 38c9dde6ff..8ec7110610 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1403,6 +1403,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, int levels[32]; const char *fname, *msg, *custom_msg, *keyword; int min = INT_MAX; + int max = INT_MAX; int i, len, nargs, nkeywords; PyObject *current_arg; freelist_t freelist = {0, NULL}; @@ -1452,8 +1453,39 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, for (i = 0; i < len; i++) { keyword = kwlist[i]; if (*format == '|') { + if (min != INT_MAX) { + PyErr_SetString(PyExc_RuntimeError, + "Invalid format string (| specified twice)"); + return cleanreturn(0, &freelist); + } + min = i; format++; + + if (max != INT_MAX) { + PyErr_SetString(PyExc_RuntimeError, + "Invalid format string ($ before |)"); + return cleanreturn(0, &freelist); + } + } + if (*format == '$') { + if (max != INT_MAX) { + PyErr_SetString(PyExc_RuntimeError, + "Invalid format string ($ specified twice)"); + return cleanreturn(0, &freelist); + } + + max = i; + format++; + + if (max < nargs) { + PyErr_Format(PyExc_TypeError, + "Function takes %s %d positional arguments" + " (%d given)", + (min != INT_MAX) ? "at most" : "exactly", + max, nargs); + return cleanreturn(0, &freelist); + } } if (IS_END_OF_FORMAT(*format)) { PyErr_Format(PyExc_RuntimeError, @@ -1514,7 +1546,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, } } - if (!IS_END_OF_FORMAT(*format) && *format != '|') { + if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) { PyErr_Format(PyExc_RuntimeError, "more argument specifiers than keyword list entries " "(remaining format:'%s')", format); -- cgit v1.2.1 From c177108b1d0ce7611272b5e1527738f7d9794b4e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Mar 2012 23:17:04 -0400 Subject: use identifier api --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 54980565bf..418237807a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1837,10 +1837,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (PyGen_CheckExact(x)) { retval = _PyGen_Send((PyGenObject *)x, u); } else { + _Py_IDENTIFIER(send); if (u == Py_None) retval = PyIter_Next(x); else - retval = PyObject_CallMethod(x, "send", "O", u); + retval = _PyObject_CallMethodId(x, &PyId_send, "O", u); } Py_DECREF(u); if (!retval) { -- cgit v1.2.1 From 6c62fbe9459a3d680a651c6216d60f87d04e1f40 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 26 Mar 2012 22:10:51 +0200 Subject: Issue #14383: Add _PyDict_GetItemId() and _PyDict_SetItemId() functions These functions simplify the usage of static constant Unicode strings. Generalize the usage of _Py_Identifier in ceval.c and typeobject.c. --- Python/ceval.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index 418237807a..ae0bd242a0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -822,6 +822,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *names; PyObject *consts; + _Py_IDENTIFIER(__ltrace__); + /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" using gcc's labels-as-values extension @@ -1198,7 +1200,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } #ifdef LLTRACE - lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; + lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL; #endif why = WHY_NOT; @@ -1926,8 +1928,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; TARGET(LOAD_BUILD_CLASS) - x = PyDict_GetItemString(f->f_builtins, - "__build_class__"); + { + _Py_IDENTIFIER(__build_class__); + x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); if (x == NULL) { PyErr_SetString(PyExc_ImportError, "__build_class__ not found"); @@ -1936,6 +1939,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_INCREF(x); PUSH(x); break; + } TARGET(STORE_NAME) w = GETITEM(names, oparg); @@ -2283,8 +2287,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); TARGET(IMPORT_NAME) + { + _Py_IDENTIFIER(__import__); w = GETITEM(names, oparg); - x = PyDict_GetItemString(f->f_builtins, "__import__"); + x = _PyDict_GetItemId(f->f_builtins, &PyId___import__); if (x == NULL) { PyErr_SetString(PyExc_ImportError, "__import__ not found"); @@ -2325,6 +2331,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) SET_TOP(x); if (x != NULL) DISPATCH(); break; + } TARGET(IMPORT_STAR) v = POP(); -- cgit v1.2.1 From e511dcc4e34ada4889ccc1d20fb3416b0add9fcb Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 2 Apr 2012 12:17:59 -0400 Subject: Guard an LLTRACE variable to silence an unused variable warning. --- Python/ceval.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python') diff --git a/Python/ceval.c b/Python/ceval.c index ae0bd242a0..7908d444e1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -822,7 +822,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *names; PyObject *consts; +#ifdef LLTRACE _Py_IDENTIFIER(__ltrace__); +#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" -- cgit v1.2.1 From 85f68bdee6df6f2426de597a97f9c33c7066570f Mon Sep 17 00:00:00 2001 From: Kristj?n Valur J?nsson Date: Tue, 3 Apr 2012 10:49:41 +0000 Subject: Issue #14288: Serialization support for builtin iterators. --- Python/bltinmodule.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) (limited to 'Python') diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 81402fc8c5..a2fb1d9a77 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -438,6 +438,19 @@ filter_next(filterobject *lz) } } +static PyObject * +filter_reduce(filterobject *lz) +{ + return Py_BuildValue("O(OO)", Py_TYPE(lz), lz->func, lz->it); +} + +PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); + +static PyMethodDef filter_methods[] = { + {"__reduce__", (PyCFunction)filter_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(filter_doc, "filter(function or None, iterable) --> filter object\n\ \n\ @@ -474,7 +487,7 @@ PyTypeObject PyFilter_Type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)filter_next, /* tp_iternext */ - 0, /* tp_methods */ + filter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -1054,6 +1067,31 @@ map_next(mapobject *lz) return result; } +static PyObject * +map_reduce(mapobject *lz) +{ + Py_ssize_t numargs = PyTuple_GET_SIZE(lz->iters); + PyObject *args = PyTuple_New(numargs+1); + Py_ssize_t i; + if (args == NULL) + return NULL; + Py_INCREF(lz->func); + PyTuple_SET_ITEM(args, 0, lz->func); + for (i = 0; iiters, i); + Py_INCREF(it); + PyTuple_SET_ITEM(args, i+1, it); + } + + return Py_BuildValue("ON", Py_TYPE(lz), args); +} + +static PyMethodDef map_methods[] = { + {"__reduce__", (PyCFunction)map_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + + PyDoc_STRVAR(map_doc, "map(func, *iterables) --> map object\n\ \n\ @@ -1090,7 +1128,7 @@ PyTypeObject PyMap_Type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)map_next, /* tp_iternext */ - 0, /* tp_methods */ + map_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -2238,6 +2276,18 @@ zip_next(zipobject *lz) return result; } +static PyObject * +zip_reduce(zipobject *lz) +{ + /* Just recreate the zip with the internal iterator tuple */ + return Py_BuildValue("OO", Py_TYPE(lz), lz->ittuple); +} + +static PyMethodDef zip_methods[] = { + {"__reduce__", (PyCFunction)zip_reduce, METH_NOARGS, reduce_doc}, + {NULL, NULL} /* sentinel */ +}; + PyDoc_STRVAR(zip_doc, "zip(iter1 [,iter2 [...]]) --> zip object\n\ \n\ @@ -2276,7 +2326,7 @@ PyTypeObject PyZip_Type = { 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ (iternextfunc)zip_next, /* tp_iternext */ - 0, /* tp_methods */ + zip_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ -- cgit v1.2.1 From 6c2c39a063041c5df28659a9766a9d67b629fd23 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Thu, 12 Apr 2012 20:24:54 -0400 Subject: Issue #1559549: Add 'name' and 'path' attributes to ImportError. Currently import does not use these attributes as they are planned for use by importlib (which will be another commit). Thanks to Filip Gruszczy?ski for the initial patch and Brian Curtin for refining it. --- Python/errors.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'Python') diff --git a/Python/errors.c b/Python/errors.c index 31fa9e2955..345a345afe 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -585,6 +585,53 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( } #endif /* MS_WINDOWS */ +PyObject * +PyErr_SetExcWithArgsKwargs(PyObject *exc, PyObject *args, PyObject *kwargs) +{ + PyObject *val; + + /* args must at least be an empty tuple */ + if (args == NULL) + args = PyTuple_New(0); + + val = PyObject_Call(exc, args, kwargs); + if (val != NULL) { + PyErr_SetObject((PyObject *) Py_TYPE(val), val); + Py_DECREF(val); + } + + return NULL; +} + +PyObject * +PyErr_SetFromImportErrorWithNameAndPath(PyObject *msg, + PyObject *name, PyObject *path) +{ + PyObject *args = PyTuple_New(1); + PyObject *kwargs = PyDict_New(); + PyObject *result; + + if (path == NULL) + path = Py_None; + + PyTuple_SetItem(args, 0, msg); + PyDict_SetItemString(kwargs, "name", name); + PyDict_SetItemString(kwargs, "path", path); + + result = PyErr_SetExcWithArgsKwargs(PyExc_ImportError, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + return result; +} + +PyObject * +PyErr_SetFromImportErrorWithName(PyObject *msg, PyObject *name) +{ + return PyErr_SetFromImportErrorWithNameAndPath(msg, name, NULL); +} + void _PyErr_BadInternalCall(const char *filename, int lineno) { -- cgit v1.2.1