Skip to content

Commit f372801

Browse files
author
guido.van.rossum
committed
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. git-svn-id: http://svn.python.org/projects/python/branches/py3k@57669 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent c898c24 commit f372801

5 files changed

Lines changed: 118 additions & 32 deletions

File tree

Doc/c-api/utilities.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,13 @@ variable(s) whose address should be passed.
484484
by interpreting their read-buffer pointer as pointer to a :ctype:`Py_UNICODE`
485485
array.
486486

487+
``Z`` (Unicode or ``None``) [Py_UNICODE \*]
488+
Like ``s``, but the Python object may also be ``None``, in which case the C
489+
pointer is set to *NULL*.
490+
491+
``Z#`` (Unicode or ``None``) [Py_UNICODE \*, int]
492+
This is to ``u#`` as ``Z`` is to ``u``.
493+
487494
``es`` (string, Unicode object or character buffer compatible object) [const char \*encoding, char \*\*buffer]
488495
This variant on ``s`` is used for encoding Unicode and objects convertible to
489496
Unicode into a character buffer. It only works for encoded data without embedded

Lib/site.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,9 @@ class open:
414414
def __new__(cls, *args, **kwds):
415415
return io.open(*args, **kwds)
416416
__builtin__.open = open
417-
sys.__stdin__ = sys.stdin = io.open(0, "r")
418-
sys.__stdout__ = sys.stdout = io.open(1, "w")
419-
sys.__stderr__ = sys.stderr = io.open(2, "w")
417+
sys.__stdin__ = sys.stdin = io.open(0, "r", newline='\n')
418+
sys.__stdout__ = sys.stdout = io.open(1, "w", newline='\n')
419+
sys.__stderr__ = sys.stderr = io.open(2, "w", newline='\n')
420420

421421

422422
def main():

Modules/_testcapimodule.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,59 @@ test_u_code(PyObject *self)
497497
return Py_None;
498498
}
499499

500+
/* Test Z and Z# codes for PyArg_ParseTuple */
501+
static PyObject *
502+
test_Z_code(PyObject *self)
503+
{
504+
PyObject *tuple, *obj;
505+
Py_UNICODE *value1, *value2;
506+
int len1, len2;
507+
508+
tuple = PyTuple_New(2);
509+
if (tuple == NULL)
510+
return NULL;
511+
512+
obj = PyUnicode_FromString("test");
513+
PyTuple_SET_ITEM(tuple, 0, obj);
514+
Py_INCREF(Py_None);
515+
PyTuple_SET_ITEM(tuple, 1, Py_None);
516+
517+
/* swap values on purpose */
518+
value1 = NULL;
519+
value2 = PyUnicode_AS_UNICODE(obj);
520+
521+
/* Test Z for both values */
522+
if (PyArg_ParseTuple(tuple, "ZZ:test_Z_code", &value1, &value2) < 0)
523+
return NULL;
524+
if (value1 != PyUnicode_AS_UNICODE(obj))
525+
return raiseTestError("test_Z_code",
526+
"Z code returned wrong value for 'test'");
527+
if (value2 != NULL)
528+
return raiseTestError("test_Z_code",
529+
"Z code returned wrong value for None");
530+
531+
value1 = NULL;
532+
value2 = PyUnicode_AS_UNICODE(obj);
533+
len1 = -1;
534+
len2 = -1;
535+
536+
/* Test Z# for both values */
537+
if (PyArg_ParseTuple(tuple, "Z#Z#:test_Z_code", &value1, &len1,
538+
&value2, &len2) < 0)
539+
return NULL;
540+
if (value1 != PyUnicode_AS_UNICODE(obj) ||
541+
len1 != PyUnicode_GET_SIZE(obj))
542+
return raiseTestError("test_Z_code",
543+
"Z# code returned wrong values for 'test'");
544+
if (value2 != NULL ||
545+
len2 != 0)
546+
return raiseTestError("test_Z_code",
547+
"Z# code returned wrong values for None'");
548+
549+
Py_DECREF(tuple);
550+
Py_RETURN_NONE;
551+
}
552+
500553
static PyObject *
501554
codec_incrementalencoder(PyObject *self, PyObject *args)
502555
{
@@ -862,6 +915,7 @@ static PyMethodDef TestMethods[] = {
862915
(PyCFunction)codec_incrementaldecoder, METH_VARARGS},
863916
#endif
864917
{"test_u_code", (PyCFunction)test_u_code, METH_NOARGS},
918+
{"test_Z_code", (PyCFunction)test_Z_code, METH_NOARGS},
865919
#ifdef WITH_THREAD
866920
{"_test_thread_state", test_thread_state, METH_VARARGS},
867921
#endif

PC/_subprocess.c

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@
3535
/* Licensed to PSF under a Contributor Agreement. */
3636
/* See http://www.python.org/2.4/license for licensing details. */
3737

38-
/* TODO: handle unicode command lines? */
39-
/* TODO: handle unicode environment? */
40-
4138
#include "Python.h"
4239

4340
#define WINDOWS_LEAN_AND_MEAN
@@ -272,7 +269,7 @@ gethandle(PyObject* obj, char* name)
272269
PyErr_Clear(); /* FIXME: propagate error? */
273270
return NULL;
274271
}
275-
if (Py_Type(&value) != &sp_handle_type)
272+
if (Py_Type(value) != &sp_handle_type)
276273
ret = NULL;
277274
else
278275
ret = value->handle;
@@ -287,7 +284,7 @@ getenvironment(PyObject* environment)
287284
PyObject* out = NULL;
288285
PyObject* keys;
289286
PyObject* values;
290-
char* p;
287+
Py_UNICODE* p;
291288

292289
/* convert environment dictionary to windows enviroment string */
293290
if (! PyMapping_Check(environment)) {
@@ -303,42 +300,42 @@ getenvironment(PyObject* environment)
303300
if (!keys || !values)
304301
goto error;
305302

306-
out = PyString_FromStringAndSize(NULL, 2048);
303+
out = PyUnicode_FromUnicode(NULL, 2048);
307304
if (! out)
308305
goto error;
309306

310-
p = PyString_AS_STRING(out);
307+
p = PyUnicode_AS_UNICODE(out);
311308

312309
for (i = 0; i < envsize; i++) {
313310
int ksize, vsize, totalsize;
314311
PyObject* key = PyList_GET_ITEM(keys, i);
315312
PyObject* value = PyList_GET_ITEM(values, i);
316313

317-
if (! PyString_Check(key) || ! PyString_Check(value)) {
314+
if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
318315
PyErr_SetString(PyExc_TypeError,
319316
"environment can only contain strings");
320317
goto error;
321318
}
322-
ksize = PyString_GET_SIZE(key);
323-
vsize = PyString_GET_SIZE(value);
324-
totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
319+
ksize = PyUnicode_GET_SIZE(key);
320+
vsize = PyUnicode_GET_SIZE(value);
321+
totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
325322
vsize + 1 + 1;
326-
if (totalsize > PyString_GET_SIZE(out)) {
327-
int offset = p - PyString_AS_STRING(out);
328-
_PyString_Resize(&out, totalsize + 1024);
329-
p = PyString_AS_STRING(out) + offset;
323+
if (totalsize > PyUnicode_GET_SIZE(out)) {
324+
int offset = p - PyUnicode_AS_UNICODE(out);
325+
PyUnicode_Resize(&out, totalsize + 1024);
326+
p = PyUnicode_AS_UNICODE(out) + offset;
330327
}
331-
memcpy(p, PyString_AS_STRING(key), ksize);
328+
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
332329
p += ksize;
333330
*p++ = '=';
334-
memcpy(p, PyString_AS_STRING(value), vsize);
331+
Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
335332
p += vsize;
336333
*p++ = '\0';
337334
}
338335

339336
/* add trailing null byte */
340337
*p++ = '\0';
341-
_PyString_Resize(&out, p - PyString_AS_STRING(out));
338+
PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
342339

343340
/* PyObject_Print(out, stdout, 0); */
344341

@@ -359,20 +356,20 @@ sp_CreateProcess(PyObject* self, PyObject* args)
359356
{
360357
BOOL result;
361358
PROCESS_INFORMATION pi;
362-
STARTUPINFO si;
359+
STARTUPINFOW si;
363360
PyObject* environment;
364361

365-
char* application_name;
366-
char* command_line;
362+
Py_UNICODE* application_name;
363+
Py_UNICODE* command_line;
367364
PyObject* process_attributes; /* ignored */
368365
PyObject* thread_attributes; /* ignored */
369366
int inherit_handles;
370367
int creation_flags;
371368
PyObject* env_mapping;
372-
char* current_directory;
369+
Py_UNICODE* current_directory;
373370
PyObject* startup_info;
374371

375-
if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
372+
if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
376373
&application_name,
377374
&command_line,
378375
&process_attributes,
@@ -406,13 +403,13 @@ sp_CreateProcess(PyObject* self, PyObject* args)
406403
}
407404

408405
Py_BEGIN_ALLOW_THREADS
409-
result = CreateProcess(application_name,
406+
result = CreateProcessW(application_name,
410407
command_line,
411408
NULL,
412409
NULL,
413410
inherit_handles,
414-
creation_flags,
415-
environment ? PyString_AS_STRING(environment) : NULL,
411+
creation_flags | CREATE_UNICODE_ENVIRONMENT,
412+
environment ? PyUnicode_AS_UNICODE(environment) : NULL,
416413
current_directory,
417414
&si,
418415
&pi);
@@ -504,18 +501,18 @@ sp_GetModuleFileName(PyObject* self, PyObject* args)
504501
{
505502
BOOL result;
506503
long module;
507-
TCHAR filename[MAX_PATH];
504+
WCHAR filename[MAX_PATH];
508505

509506
if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
510507
return NULL;
511508

512-
result = GetModuleFileName((HMODULE)module, filename, MAX_PATH);
509+
result = GetModuleFileNameW((HMODULE)module, filename, MAX_PATH);
513510
filename[MAX_PATH-1] = '\0';
514511

515512
if (! result)
516513
return PyErr_SetFromWindowsErr(GetLastError());
517514

518-
return PyString_FromString(filename);
515+
return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
519516
}
520517

521518
static PyMethodDef sp_functions[] = {

Python/getargs.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,34 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
921921
break;
922922
}
923923

924+
case 'Z': {/* unicode, may be NULL (None) */
925+
if (*format == '#') { /* any buffer-like object */
926+
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
927+
FETCH_SIZE;
928+
929+
if (arg == Py_None) {
930+
*p = 0;
931+
STORE_SIZE(0);
932+
}
933+
else if (PyUnicode_Check(arg)) {
934+
*p = PyUnicode_AS_UNICODE(arg);
935+
STORE_SIZE(PyUnicode_GET_SIZE(arg));
936+
}
937+
format++;
938+
} else {
939+
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
940+
941+
if (arg == Py_None)
942+
*p = 0;
943+
else if (PyUnicode_Check(arg))
944+
*p = PyUnicode_AS_UNICODE(arg);
945+
else
946+
return converterr("string or None",
947+
arg, msgbuf, bufsize);
948+
}
949+
break;
950+
}
951+
924952
case 'e': {/* encoded string */
925953
char **buffer;
926954
const char *encoding;

0 commit comments

Comments
 (0)