Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (révision 81377) +++ Python/pythonrun.c (copie de travail) @@ -490,6 +490,15 @@ Py_FileSystemDefaultEncoding = NULL; } + /* reset command line arguments encoding */ + if (Py_FreeCommandLineEncoding) { + if (Py_CommandLineEncoding) { + free((char*)Py_CommandLineEncoding); + Py_CommandLineEncoding = NULL; + } + Py_FreeCommandLineEncoding = 0; + } + /* XXX Still allocated: - various static ad-hoc pointers to interned strings - int and float free list blocks @@ -700,27 +709,50 @@ initfsencoding(void) { PyObject *codec; + #if defined(HAVE_LANGINFO_H) && defined(CODESET) char *codeset; - /* 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. Also set the encoding of - stdin and stdout if these are terminals. */ - codeset = get_codeset(); - if (codeset != NULL) { - Py_FileSystemDefaultEncoding = codeset; - Py_HasFileSystemDefaultEncoding = 0; - return; + if (Py_FileSystemDefaultEncoding == NULL + || Py_CommandLineEncoding == 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. Also set the encoding of + stdin and stdout if these are terminals. */ + codeset = get_codeset(); + if (codeset != NULL) { + if (Py_FileSystemDefaultEncoding == NULL) { + Py_FileSystemDefaultEncoding = codeset; + Py_HasFileSystemDefaultEncoding = 0; + } + if (Py_CommandLineEncoding == NULL) { + Py_CommandLineEncoding = strdup(codeset); +#if 0 + if (Py_CommandLineEncoding == 0) { + FIXME! + PyErr_NoMemory(); + } +#endif + Py_FreeCommandLineEncoding = 1; + } + return; + } + + PyErr_Clear(); + fprintf(stderr, + "Unable to get the locale encoding: " + "fallback to utf-8\n"); + if (Py_FileSystemDefaultEncoding == NULL) { + Py_FileSystemDefaultEncoding = "utf-8"; + Py_HasFileSystemDefaultEncoding = 1; + } + if (Py_CommandLineEncoding == NULL) { + Py_CommandLineEncoding = "utf-8"; + Py_FreeCommandLineEncoding = 0; + } } - - PyErr_Clear(); - fprintf(stderr, - "Unable to get the locale encoding: " - "fallback to utf-8\n"); - Py_FileSystemDefaultEncoding = "utf-8"; - Py_HasFileSystemDefaultEncoding = 1; #endif /* the encoding is mbcs, utf-8 or ascii */ Index: Python/bltinmodule.c =================================================================== --- Python/bltinmodule.c (révision 81377) +++ Python/bltinmodule.c (copie de travail) @@ -22,16 +22,21 @@ #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) const char *Py_FileSystemDefaultEncoding = "mbcs"; int Py_HasFileSystemDefaultEncoding = 1; -#elif defined(__APPLE__) +const char *Py_CommandLineEncoding = "mbcs"; +#else +const char *Py_CommandLineEncoding = NULL; +# if defined(__APPLE__) const char *Py_FileSystemDefaultEncoding = "utf-8"; int Py_HasFileSystemDefaultEncoding = 1; -#elif defined(HAVE_LANGINFO_H) && defined(CODESET) +# elif defined(HAVE_LANGINFO_H) && defined(CODESET) const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ int Py_HasFileSystemDefaultEncoding = 0; -#else +# else const char *Py_FileSystemDefaultEncoding = "utf-8"; int Py_HasFileSystemDefaultEncoding = 1; +# endif #endif +int Py_FreeCommandLineEncoding = 0; int _Py_SetFileSystemEncoding(PyObject *s) Index: Python/sysmodule.c =================================================================== --- Python/sysmodule.c (révision 81377) +++ Python/sysmodule.c (copie de travail) @@ -217,6 +217,22 @@ ); static PyObject * +sys_getcmdlineencoding(PyObject *self) +{ + if (Py_CommandLineEncoding) + return PyUnicode_FromString(Py_CommandLineEncoding); + Py_INCREF(Py_None); + return Py_None; +} + +PyDoc_STRVAR(getcmdlineencoding_doc, +"getcmdlineencoding() -> string\n\ +\n\ +Return the encoding used to convert Unicode command line arguments in\n\ +operating system arguments." +); + +static PyObject * sys_setfilesystemencoding(PyObject *self, PyObject *args) { PyObject *new_encoding; @@ -959,6 +975,8 @@ #endif {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding, METH_NOARGS, getfilesystemencoding_doc}, + {"getcmdlineencoding", (PyCFunction)sys_getcmdlineencoding, + METH_NOARGS, getcmdlineencoding_doc}, #ifdef Py_TRACE_REFS {"getobjects", _Py_GetObjects, METH_VARARGS}, #endif Index: Include/fileobject.h =================================================================== --- Include/fileobject.h (révision 81377) +++ Include/fileobject.h (copie de travail) @@ -16,6 +16,12 @@ PyAPI_FUNC(int) PyObject_AsFileDescriptor(PyObject *); PyAPI_FUNC(char *) Py_UniversalNewlineFgets(char *, int, FILE*, PyObject *); +/* The encoding used to encode and decode command line arguments. + If non-NULL, this is different than the default encoding for strings +*/ +PyAPI_DATA(const char *) Py_CommandLineEncoding; +PyAPI_DATA(int) Py_FreeCommandLineEncoding; + /* The default encoding used by the platform file system APIs If non-NULL, this is different than the default encoding for strings */ Index: Lib/subprocess.py =================================================================== --- Lib/subprocess.py (révision 81377) +++ Lib/subprocess.py (copie de travail) @@ -1116,6 +1116,9 @@ # This implementation may deadlock in the child if your # parent process has any other threads running. + encoding = sys.getcmdlineencoding() + args = [arg.encode(encoding, 'surrogateescape') for arg in args] + gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. See issue1336 Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (révision 81377) +++ Modules/posixmodule.c (copie de travail) @@ -2950,12 +2950,24 @@ } static -int fsconvert_strdup(PyObject *o, char**out) +int convert_argv_strdup(PyObject *o, char**out) { PyObject *bytes; Py_ssize_t size; - if (!PyUnicode_FSConverter(o, &bytes)) + + if (PyUnicode_Check(o)) { + bytes = PyUnicode_AsEncodedString(o, Py_CommandLineEncoding, "surrogateescape"); + if (bytes == NULL) + return 0; + } else if (PyBytes_Check(o)) { + Py_INCREF(o); + bytes = o; + } else { + PyErr_Format(PyExc_TypeError, + "expect str or bytes argument, not %s", + Py_TYPE(o)->tp_name); return 0; + } size = PyBytes_GET_SIZE(bytes); *out = PyMem_Malloc(size+1); if (!*out) @@ -3018,8 +3030,8 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString(PyExc_TypeError, "execv() arg 2 must contain only strings"); @@ -3174,8 +3186,8 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { lastarg = i; goto fail_1; @@ -3256,8 +3268,8 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( PyExc_TypeError, @@ -3353,8 +3365,8 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { lastarg = i; goto fail_1; @@ -3450,8 +3462,8 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( PyExc_TypeError, @@ -3538,8 +3550,8 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) + if (!convert_argv_strdup((*getitem)(argv, i), + &argvlist[i])) { lastarg = i; goto fail_1; Index: Modules/_posixsubprocess.c =================================================================== --- Modules/_posixsubprocess.c (révision 81377) +++ Modules/_posixsubprocess.c (copie de travail) @@ -243,8 +243,18 @@ for (arg_num = 0; arg_num < num_args; ++arg_num) { PyObject *borrowed_arg, *converted_arg; borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); - if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) - goto cleanup; + if (PyUnicode_Check(borrowed_arg)) { + converted_arg = PyUnicode_AsEncodedString(borrowed_arg, Py_CommandLineEncoding, "surrogateescape"); + if (converted_arg == NULL) + goto cleanup; + } else if (PyBytes_Check(borrowed_arg)) { + Py_INCREF(borrowed_arg); + converted_arg = borrowed_arg; + } else { + PyErr_Format(PyExc_TypeError, + "expect str or bytes argument, not %s", + Py_TYPE(borrowed_arg)->tp_name); + } PyTuple_SET_ITEM(converted_args, arg_num, converted_arg); }