Issue #20368: The null character now correctly passed from Tcl to Python.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 3 Feb 2014 19:25:56 +0000 (21:25 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 3 Feb 2014 19:25:56 +0000 (21:25 +0200)
Improved error handling in variables-related commands.

1  2 
Lib/test/test_tcl.py
Misc/NEWS
Modules/_tkinter.c

Simple merge
diff --cc Misc/NEWS
index f6d908d4dcd1b1e8f5bd0235335d753273201c94,66d9db79524dbb0eb056b10f138cd024fb7404d1..d5befa66e2afe20ec82511cf28ffbb5ad081d06c
+++ b/Misc/NEWS
@@@ -10,39 -10,46 +10,42 @@@ Release date: 2014-02-0
  Core and Builtins
  -----------------
  
 -- Issue #17825: Cursor "^" is correctly positioned for SyntaxError and
 -  IndentationError.
 -
 -- Issue #2382: SyntaxError cursor "^" is now written at correct position in most
 -  cases when multibyte characters are in line (before "^").  This still not
 -  works correctly with wide East Asian characters.
 +- Issue #20162: Fix an alignment issue in the siphash24() hash function which
 +  caused a crash on PowerPC 64-bit (ppc64).
  
 -- Issue #18960: The first line of Python script could be executed twice when
 -  the source encoding was specified on the second line.  Now the source encoding
 -  declaration on the second line isn't effective if the first line contains
 -  anything except a comment.  'python -x' works now again with files with the
 -  source encoding declarations, and can be used to make Python batch files
 -  on Windows.
 +Library
 +-------
  
 -- Issue #17432: Drop UCS2 from names of Unicode functions in python3.def.
++- Issue #20368: The null character now correctly passed from Tcl to Python.
++  Improved error handling in variables-related commands.
 -- Issue #19969: PyBytes_FromFormatV() now raises an OverflowError if "%c"
 -  argument is not in range [0; 255].
 +- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline
 +  translation settings.
  
 -- Issue #14432: Generator now clears the borrowed reference to the thread
 -  state. Fix a crash when a generator is created in a C thread that is
 -  destroyed while the generator is still used. The issue was that a generator
 -  contains a frame, and the frame kept a reference to the Python state of the
 -  destroyed C thread. The crash occurs when a trace function is setup.
 +- tracemalloc: Fix slicing traces and fix slicing a traceback.
  
 -- Issue #19932: Fix typo in import.h, missing whitespaces in function prototypes.
 +- Issue #20354: Fix an alignment issue in the tracemalloc module on 64-bit
 +  platforms. Bug seen on 64-bit Linux when using "make profile-opt".
  
 -- Issue #19729: In str.format(), fix recursive expansion in format spec.
 +- Issue #17159: inspect.signature now accepts duck types of functions,
 +  which adds support for Cython functions. Initial patch by Stefan Behnel.
  
 -- Issue #19638: Fix possible crash / undefined behaviour from huge (more than 2
 -  billion characters) input strings in _Py_dg_strtod.
 +- Issue #18801: Fix inspect.classify_class_attrs to correctly classify
 +  object.__new__ and object.__init__.
  
 -Library
 --------
 +- Fixed cmath.isinf's name in its argument parsing code.
  
 -- Issue #20368: The null character now correctly passed from Tcl to Python.
 -  Improved error handling in variables-related commands.
 +- Issue #20311, #20452: poll and epoll now round the timeout away from zero,
 +  instead of rounding towards zero, in select and selectors modules:
 +  select.epoll.poll(), selectors.PollSelector.poll() and
 +  selectors.EpollSelector.poll(). For example, a timeout of one microsecond
 +  (1e-6) is now rounded to one millisecondi (1e-3), instead of being rounded to
 +  zero.
  
 -- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline
 -  translation settings.
 +- asyncio: Some refactoring; add write flow control to unix pipes;
 +  support wait_for(f, None); don't log broken/disconnected pipes; use
 +  ValueError instead of assert for forbidden subprocess_{shell,exec}
 +  arguments.  (More to follow -- a convenience API for subprocesses.)
  
  - Issue #20288: fix handling of invalid numeric charrefs in HTMLParser.
  
index 92dd94c4bef1e69d5b52e4e4f77fdc6bf4a82aeb,b106b4b901167fa262f36f9a7bd7f43ba411e509..d48fb179f36e58e4bfcd2a69f1d1cca121fb4000
@@@ -326,8 -315,154 +326,53 @@@ WaitForMainloop(TkappObject* self
  
  #define ARGSZ 64
  
 -static char *
 -Merge(PyObject *args)
 -{
 -    PyObject *tmp = NULL;
 -    char *argvStore[ARGSZ];
 -    char **argv = NULL;
 -    int fvStore[ARGSZ];
 -    int *fv = NULL;
 -    Py_ssize_t argc = 0, fvc = 0, i;
 -    char *res = NULL;
 -
 -    if (!(tmp = PyList_New(0)))
 -        return NULL;
 -
 -    argv = argvStore;
 -    fv = fvStore;
 -
 -    if (args == NULL)
 -        argc = 0;
 -
 -    else if (!PyTuple_Check(args)) {
 -        argc = 1;
 -        fv[0] = 0;
 -        if (!(argv[0] = AsString(args, tmp)))
 -            goto finally;
 -    }
 -    else {
 -        argc = PyTuple_Size(args);
 -
 -        if (argc > ARGSZ) {
 -            if (!CHECK_SIZE(argc, sizeof(char *))) {
 -                PyErr_SetString(PyExc_OverflowError, "tuple is too long");
 -                goto finally;
 -            }
 -            argv = (char **)ckalloc((size_t)argc * sizeof(char *));
 -            fv = (int *)ckalloc((size_t)argc * sizeof(int));
 -            if (argv == NULL || fv == NULL) {
 -                PyErr_NoMemory();
 -                goto finally;
 -            }
 -        }
 -
 -        for (i = 0; i < argc; i++) {
 -            PyObject *v = PyTuple_GetItem(args, i);
 -            if (PyTuple_Check(v)) {
 -                fv[i] = 1;
 -                if (!(argv[i] = Merge(v)))
 -                    goto finally;
 -                fvc++;
 -            }
 -            else if (v == Py_None) {
 -                argc = i;
 -                break;
 -            }
 -            else {
 -                fv[i] = 0;
 -                if (!(argv[i] = AsString(v, tmp)))
 -                    goto finally;
 -                fvc++;
 -            }
 -        }
 -    }
 -    res = Tcl_Merge(argc, argv);
 -    if (res == NULL)
 -        PyErr_SetString(Tkinter_TclError, "merge failed");
 -
 -  finally:
 -    for (i = 0; i < fvc; i++)
 -        if (fv[i]) {
 -            ckfree(argv[i]);
 -        }
 -    if (argv != argvStore)
 -        ckfree(FREECAST argv);
 -    if (fv != fvStore)
 -        ckfree(FREECAST fv);
 -
 -    Py_DECREF(tmp);
 -    return res;
 -}
 -
  
  
+ static PyObject *
+ unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
+ {
+     PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
+     if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
+         /* Tcl encodes null character as \xc0\x80 */
+         if (memchr(s, '\xc0', size)) {
+             char *buf, *q;
+             const char *e = s + size;
+             PyErr_Clear();
+             q = buf = (char *)PyMem_Malloc(size);
+             if (buf == NULL)
+                 return NULL;
+             while (s != e) {
+                 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
+                     *q++ = '\0';
+                     s += 2;
+                 }
+                 else
+                     *q++ = *s++;
+             }
+             s = buf;
+             size = q - s;
+             r = PyUnicode_DecodeUTF8(s, size, NULL);
+             PyMem_Free(buf);
+         }
+     }
+     return r;
+ }
+ static PyObject *
+ unicodeFromTclString(const char *s)
+ {
+     return unicodeFromTclStringAndSize(s, strlen(s));
+ }
+ static PyObject *
+ unicodeFromTclObj(Tcl_Obj *value)
+ {
+     int len;
+     char *s = Tcl_GetStringFromObj(value, &len);
+     return unicodeFromTclStringAndSize(s, len);
+ }
  static PyObject *
  Split(char *list)
  {