Three patches from issue #1047, by Amaury Forgeot d'Arc:
1/ getargs.diff adds the 'Z' and 'Z#' format specifiers for PyArg_ParseTuple. They mimic z and z# for unicode strings, by accepting a Unicode or None (in which case the Py_UNICODE* pointer is set to NULL). With doc and tests. 2/ subprocess.diff converts file PC/_subprocess.c to unicode. We use the Unicode version of the win32 api (and Z conversion from previous patch) 3/ stdout.diff: sys.stdout must not convert the line endings, Windows already does it. Without this patch, when redirecting the output of python, the file contains \r\r\n for each line. (test_subprocess did catch this) However, I (GvR) removed the change to _fileio.c (included in the patches) that prevents closing file descripors < 3 from being closed; I think that needs to be solved in a different way.
This commit is contained in:
parent
e86254e256
commit
fb67be2f6b
|
@ -484,6 +484,13 @@ variable(s) whose address should be passed.
|
||||||
by interpreting their read-buffer pointer as pointer to a :ctype:`Py_UNICODE`
|
by interpreting their read-buffer pointer as pointer to a :ctype:`Py_UNICODE`
|
||||||
array.
|
array.
|
||||||
|
|
||||||
|
``Z`` (Unicode or ``None``) [Py_UNICODE \*]
|
||||||
|
Like ``s``, but the Python object may also be ``None``, in which case the C
|
||||||
|
pointer is set to *NULL*.
|
||||||
|
|
||||||
|
``Z#`` (Unicode or ``None``) [Py_UNICODE \*, int]
|
||||||
|
This is to ``u#`` as ``Z`` is to ``u``.
|
||||||
|
|
||||||
``es`` (string, Unicode object or character buffer compatible object) [const char \*encoding, char \*\*buffer]
|
``es`` (string, Unicode object or character buffer compatible object) [const char \*encoding, char \*\*buffer]
|
||||||
This variant on ``s`` is used for encoding Unicode and objects convertible to
|
This variant on ``s`` is used for encoding Unicode and objects convertible to
|
||||||
Unicode into a character buffer. It only works for encoded data without embedded
|
Unicode into a character buffer. It only works for encoded data without embedded
|
||||||
|
|
|
@ -414,9 +414,9 @@ def installnewio():
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
return io.open(*args, **kwds)
|
return io.open(*args, **kwds)
|
||||||
__builtin__.open = open
|
__builtin__.open = open
|
||||||
sys.__stdin__ = sys.stdin = io.open(0, "r")
|
sys.__stdin__ = sys.stdin = io.open(0, "r", newline='\n')
|
||||||
sys.__stdout__ = sys.stdout = io.open(1, "w")
|
sys.__stdout__ = sys.stdout = io.open(1, "w", newline='\n')
|
||||||
sys.__stderr__ = sys.stderr = io.open(2, "w")
|
sys.__stderr__ = sys.stderr = io.open(2, "w", newline='\n')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
|
@ -497,6 +497,59 @@ test_u_code(PyObject *self)
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test Z and Z# codes for PyArg_ParseTuple */
|
||||||
|
static PyObject *
|
||||||
|
test_Z_code(PyObject *self)
|
||||||
|
{
|
||||||
|
PyObject *tuple, *obj;
|
||||||
|
Py_UNICODE *value1, *value2;
|
||||||
|
int len1, len2;
|
||||||
|
|
||||||
|
tuple = PyTuple_New(2);
|
||||||
|
if (tuple == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
obj = PyUnicode_FromString("test");
|
||||||
|
PyTuple_SET_ITEM(tuple, 0, obj);
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
PyTuple_SET_ITEM(tuple, 1, Py_None);
|
||||||
|
|
||||||
|
/* swap values on purpose */
|
||||||
|
value1 = NULL;
|
||||||
|
value2 = PyUnicode_AS_UNICODE(obj);
|
||||||
|
|
||||||
|
/* Test Z for both values */
|
||||||
|
if (PyArg_ParseTuple(tuple, "ZZ:test_Z_code", &value1, &value2) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (value1 != PyUnicode_AS_UNICODE(obj))
|
||||||
|
return raiseTestError("test_Z_code",
|
||||||
|
"Z code returned wrong value for 'test'");
|
||||||
|
if (value2 != NULL)
|
||||||
|
return raiseTestError("test_Z_code",
|
||||||
|
"Z code returned wrong value for None");
|
||||||
|
|
||||||
|
value1 = NULL;
|
||||||
|
value2 = PyUnicode_AS_UNICODE(obj);
|
||||||
|
len1 = -1;
|
||||||
|
len2 = -1;
|
||||||
|
|
||||||
|
/* Test Z# for both values */
|
||||||
|
if (PyArg_ParseTuple(tuple, "Z#Z#:test_Z_code", &value1, &len1,
|
||||||
|
&value2, &len2) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (value1 != PyUnicode_AS_UNICODE(obj) ||
|
||||||
|
len1 != PyUnicode_GET_SIZE(obj))
|
||||||
|
return raiseTestError("test_Z_code",
|
||||||
|
"Z# code returned wrong values for 'test'");
|
||||||
|
if (value2 != NULL ||
|
||||||
|
len2 != 0)
|
||||||
|
return raiseTestError("test_Z_code",
|
||||||
|
"Z# code returned wrong values for None'");
|
||||||
|
|
||||||
|
Py_DECREF(tuple);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
codec_incrementalencoder(PyObject *self, PyObject *args)
|
codec_incrementalencoder(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -862,6 +915,7 @@ static PyMethodDef TestMethods[] = {
|
||||||
(PyCFunction)codec_incrementaldecoder, METH_VARARGS},
|
(PyCFunction)codec_incrementaldecoder, METH_VARARGS},
|
||||||
#endif
|
#endif
|
||||||
{"test_u_code", (PyCFunction)test_u_code, METH_NOARGS},
|
{"test_u_code", (PyCFunction)test_u_code, METH_NOARGS},
|
||||||
|
{"test_Z_code", (PyCFunction)test_Z_code, METH_NOARGS},
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
{"_test_thread_state", test_thread_state, METH_VARARGS},
|
{"_test_thread_state", test_thread_state, METH_VARARGS},
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
/* Licensed to PSF under a Contributor Agreement. */
|
/* Licensed to PSF under a Contributor Agreement. */
|
||||||
/* See http://www.python.org/2.4/license for licensing details. */
|
/* See http://www.python.org/2.4/license for licensing details. */
|
||||||
|
|
||||||
/* TODO: handle unicode command lines? */
|
|
||||||
/* TODO: handle unicode environment? */
|
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
#define WINDOWS_LEAN_AND_MEAN
|
#define WINDOWS_LEAN_AND_MEAN
|
||||||
|
@ -272,7 +269,7 @@ gethandle(PyObject* obj, char* name)
|
||||||
PyErr_Clear(); /* FIXME: propagate error? */
|
PyErr_Clear(); /* FIXME: propagate error? */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (Py_Type(&value) != &sp_handle_type)
|
if (Py_Type(value) != &sp_handle_type)
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
else
|
else
|
||||||
ret = value->handle;
|
ret = value->handle;
|
||||||
|
@ -287,7 +284,7 @@ getenvironment(PyObject* environment)
|
||||||
PyObject* out = NULL;
|
PyObject* out = NULL;
|
||||||
PyObject* keys;
|
PyObject* keys;
|
||||||
PyObject* values;
|
PyObject* values;
|
||||||
char* p;
|
Py_UNICODE* p;
|
||||||
|
|
||||||
/* convert environment dictionary to windows enviroment string */
|
/* convert environment dictionary to windows enviroment string */
|
||||||
if (! PyMapping_Check(environment)) {
|
if (! PyMapping_Check(environment)) {
|
||||||
|
@ -303,42 +300,42 @@ getenvironment(PyObject* environment)
|
||||||
if (!keys || !values)
|
if (!keys || !values)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
out = PyString_FromStringAndSize(NULL, 2048);
|
out = PyUnicode_FromUnicode(NULL, 2048);
|
||||||
if (! out)
|
if (! out)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
p = PyString_AS_STRING(out);
|
p = PyUnicode_AS_UNICODE(out);
|
||||||
|
|
||||||
for (i = 0; i < envsize; i++) {
|
for (i = 0; i < envsize; i++) {
|
||||||
int ksize, vsize, totalsize;
|
int ksize, vsize, totalsize;
|
||||||
PyObject* key = PyList_GET_ITEM(keys, i);
|
PyObject* key = PyList_GET_ITEM(keys, i);
|
||||||
PyObject* value = PyList_GET_ITEM(values, i);
|
PyObject* value = PyList_GET_ITEM(values, i);
|
||||||
|
|
||||||
if (! PyString_Check(key) || ! PyString_Check(value)) {
|
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"environment can only contain strings");
|
"environment can only contain strings");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ksize = PyString_GET_SIZE(key);
|
ksize = PyUnicode_GET_SIZE(key);
|
||||||
vsize = PyString_GET_SIZE(value);
|
vsize = PyUnicode_GET_SIZE(value);
|
||||||
totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
|
totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
|
||||||
vsize + 1 + 1;
|
vsize + 1 + 1;
|
||||||
if (totalsize > PyString_GET_SIZE(out)) {
|
if (totalsize > PyUnicode_GET_SIZE(out)) {
|
||||||
int offset = p - PyString_AS_STRING(out);
|
int offset = p - PyUnicode_AS_UNICODE(out);
|
||||||
_PyString_Resize(&out, totalsize + 1024);
|
PyUnicode_Resize(&out, totalsize + 1024);
|
||||||
p = PyString_AS_STRING(out) + offset;
|
p = PyUnicode_AS_UNICODE(out) + offset;
|
||||||
}
|
}
|
||||||
memcpy(p, PyString_AS_STRING(key), ksize);
|
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
|
||||||
p += ksize;
|
p += ksize;
|
||||||
*p++ = '=';
|
*p++ = '=';
|
||||||
memcpy(p, PyString_AS_STRING(value), vsize);
|
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
|
||||||
p += vsize;
|
p += vsize;
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add trailing null byte */
|
/* add trailing null byte */
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
_PyString_Resize(&out, p - PyString_AS_STRING(out));
|
PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
|
||||||
|
|
||||||
/* PyObject_Print(out, stdout, 0); */
|
/* PyObject_Print(out, stdout, 0); */
|
||||||
|
|
||||||
|
@ -359,20 +356,20 @@ sp_CreateProcess(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
BOOL result;
|
BOOL result;
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
STARTUPINFO si;
|
STARTUPINFOW si;
|
||||||
PyObject* environment;
|
PyObject* environment;
|
||||||
|
|
||||||
char* application_name;
|
Py_UNICODE* application_name;
|
||||||
char* command_line;
|
Py_UNICODE* command_line;
|
||||||
PyObject* process_attributes; /* ignored */
|
PyObject* process_attributes; /* ignored */
|
||||||
PyObject* thread_attributes; /* ignored */
|
PyObject* thread_attributes; /* ignored */
|
||||||
int inherit_handles;
|
int inherit_handles;
|
||||||
int creation_flags;
|
int creation_flags;
|
||||||
PyObject* env_mapping;
|
PyObject* env_mapping;
|
||||||
char* current_directory;
|
Py_UNICODE* current_directory;
|
||||||
PyObject* startup_info;
|
PyObject* startup_info;
|
||||||
|
|
||||||
if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
|
if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
|
||||||
&application_name,
|
&application_name,
|
||||||
&command_line,
|
&command_line,
|
||||||
&process_attributes,
|
&process_attributes,
|
||||||
|
@ -406,13 +403,13 @@ sp_CreateProcess(PyObject* self, PyObject* args)
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
result = CreateProcess(application_name,
|
result = CreateProcessW(application_name,
|
||||||
command_line,
|
command_line,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
inherit_handles,
|
inherit_handles,
|
||||||
creation_flags,
|
creation_flags | CREATE_UNICODE_ENVIRONMENT,
|
||||||
environment ? PyString_AS_STRING(environment) : NULL,
|
environment ? PyUnicode_AS_UNICODE(environment) : NULL,
|
||||||
current_directory,
|
current_directory,
|
||||||
&si,
|
&si,
|
||||||
&pi);
|
&pi);
|
||||||
|
@ -504,18 +501,18 @@ sp_GetModuleFileName(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
BOOL result;
|
BOOL result;
|
||||||
long module;
|
long module;
|
||||||
TCHAR filename[MAX_PATH];
|
WCHAR filename[MAX_PATH];
|
||||||
|
|
||||||
if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
|
if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
result = GetModuleFileName((HMODULE)module, filename, MAX_PATH);
|
result = GetModuleFileNameW((HMODULE)module, filename, MAX_PATH);
|
||||||
filename[MAX_PATH-1] = '\0';
|
filename[MAX_PATH-1] = '\0';
|
||||||
|
|
||||||
if (! result)
|
if (! result)
|
||||||
return PyErr_SetFromWindowsErr(GetLastError());
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
|
|
||||||
return PyString_FromString(filename);
|
return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyMethodDef sp_functions[] = {
|
static PyMethodDef sp_functions[] = {
|
||||||
|
|
|
@ -921,6 +921,34 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'Z': {/* unicode, may be NULL (None) */
|
||||||
|
if (*format == '#') { /* any buffer-like object */
|
||||||
|
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
|
||||||
|
FETCH_SIZE;
|
||||||
|
|
||||||
|
if (arg == Py_None) {
|
||||||
|
*p = 0;
|
||||||
|
STORE_SIZE(0);
|
||||||
|
}
|
||||||
|
else if (PyUnicode_Check(arg)) {
|
||||||
|
*p = PyUnicode_AS_UNICODE(arg);
|
||||||
|
STORE_SIZE(PyUnicode_GET_SIZE(arg));
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
} else {
|
||||||
|
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
|
||||||
|
|
||||||
|
if (arg == Py_None)
|
||||||
|
*p = 0;
|
||||||
|
else if (PyUnicode_Check(arg))
|
||||||
|
*p = PyUnicode_AS_UNICODE(arg);
|
||||||
|
else
|
||||||
|
return converterr("string or None",
|
||||||
|
arg, msgbuf, bufsize);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'e': {/* encoded string */
|
case 'e': {/* encoded string */
|
||||||
char **buffer;
|
char **buffer;
|
||||||
const char *encoding;
|
const char *encoding;
|
||||||
|
|
Loading…
Reference in New Issue