Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (révision 85117) +++ Python/pythonrun.c (copie de travail) @@ -513,6 +513,13 @@ Py_FileSystemDefaultEncoding = NULL; } + /* reset command line arguments encoding */ + if (Py_FreeCommandLineEncoding) { + Py_FreeCommandLineEncoding = 0; + free((char*)Py_CommandLineEncoding); + Py_CommandLineEncoding = NULL; + } + /* XXX Still allocated: - various static ad-hoc pointers to interned strings - int and float free list blocks @@ -977,7 +984,15 @@ { PyObject *codec; #if defined(HAVE_LANGINFO_H) && defined(CODESET) - char *codeset = NULL; + char *codeset; + + if (Py_CommandLineEncoding == NULL) { + codeset = get_codeset(); + if (codeset == NULL) + Py_FatalError("Py_Initialize: Unable to get the locale encoding:\n"); + Py_CommandLineEncoding = codeset; + Py_FreeCommandLineEncoding = 1; + } if (Py_FileSystemDefaultEncoding == NULL) { const char *env_encoding = Py_GETENV("PYTHONFSENCODING"); @@ -988,6 +1003,8 @@ PyErr_Print(); } } + else + codeset = NULL; if (!codeset) { /* On Unix, set the file system encoding according to the user's preference, if the CODESET names a well-known Index: Python/bltinmodule.c =================================================================== --- Python/bltinmodule.c (révision 85117) +++ Python/bltinmodule.c (copie de travail) @@ -22,16 +22,23 @@ #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"; +const char *Py_CommandLineErrors = "strict"; +#else +const char *Py_CommandLineEncoding = NULL; +const char *Py_CommandLineErrors = "surrogateescape"; +# 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; static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) Index: Python/sysmodule.c =================================================================== --- Python/sysmodule.c (révision 85117) +++ Python/sysmodule.c (copie de travail) @@ -199,6 +199,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_intern(PyObject *self, PyObject *args) { PyObject *s; @@ -973,6 +989,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 85117) +++ Include/fileobject.h (copie de travail) @@ -16,6 +16,11 @@ 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 */ +PyAPI_DATA(const char *) Py_CommandLineEncoding; +PyAPI_DATA(const char *) Py_CommandLineErrors; +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 85117) +++ Lib/subprocess.py (copie de travail) @@ -1086,6 +1086,14 @@ try: self._set_cloexec_flag(errpipe_write) + cmdline_encoding = sys.getcmdlineencoding() + def _encode_arg(arg): + if isinstance(arg, str): + return arg.encode(cmdline_encoding, 'surrogateescape') + else: + return arg + args = [_encode_arg(arg) for arg in args] + if _posixsubprocess: # We must avoid complex work that could involve # malloc or free in the child process to avoid Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (révision 85117) +++ Modules/posixmodule.c (copie de travail) @@ -3277,12 +3277,25 @@ } 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, Py_CommandLineErrors); + 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) @@ -3345,7 +3358,7 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString(PyExc_TypeError, @@ -3501,7 +3514,7 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { lastarg = i; @@ -3583,7 +3596,7 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( @@ -3680,7 +3693,7 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { lastarg = i; @@ -3777,7 +3790,7 @@ return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { free_string_array(argvlist, i); PyErr_SetString( @@ -3866,7 +3879,7 @@ goto fail_0; } for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), + if (!convert_argv_strdup((*getitem)(argv, i), &argvlist[i])) { lastarg = i; Index: Modules/_posixsubprocess.c =================================================================== --- Modules/_posixsubprocess.c (révision 85117) +++ Modules/_posixsubprocess.c (copie de travail) @@ -241,11 +241,16 @@ if (converted_args == NULL) goto cleanup; for (arg_num = 0; arg_num < num_args; ++arg_num) { - PyObject *borrowed_arg, *converted_arg; + PyObject *borrowed_arg; borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); - if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) + if (!PyBytes_Check(borrowed_arg)) { + PyErr_Format(PyExc_TypeError, + "expect str or bytes argument, not %s", + Py_TYPE(borrowed_arg)->tp_name); goto cleanup; - PyTuple_SET_ITEM(converted_args, arg_num, converted_arg); + } + Py_INCREF(borrowed_arg); + PyTuple_SET_ITEM(converted_args, arg_num, borrowed_arg); } argv = _PySequence_BytesToCharpArray(converted_args);