summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2019-10-04 10:09:52 (GMT)
committerGitHub <noreply@github.com>2019-10-04 10:09:52 (GMT)
commit06cb94bc8419b9a24df6b0d724fcd8e40c6971d6 (patch)
tree61dff1fe122eac251b43b7994f7deb40f1b9efcc /Modules
parent2290b23dfc9cce71ffc49bfcb6a5a16c570cefae (diff)
downloadcpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.zip
cpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.tar.gz
cpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.tar.bz2
bpo-13153: Use OS native encoding for converting between Python and Tcl. (GH-16545)
On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the "surrogatepass" error handler for converting to/from Tcl Unicode objects. On Linux use UTF-8 with the "surrogateescape" error handler for converting to/from Tcl String objects. Converting strings from Tcl to Python and back now never fails (except MemoryError).
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_tkinter.c375
1 files changed, 202 insertions, 173 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 94d5b64..c431d61 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -96,6 +96,24 @@ Copyright (C) 1994 Steen Lumholt.
#endif /* HAVE_CREATEFILEHANDLER */
+/* Use OS native encoding for converting between Python strings and
+ Tcl objects.
+ On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
+ "surrogatepass" error handler for converting to/from Tcl Unicode objects.
+ On Linux use UTF-8 with the "surrogateescape" error handler for converting
+ to/from Tcl String objects. */
+#ifdef MS_WINDOWS
+#define USE_TCL_UNICODE 1
+#else
+#define USE_TCL_UNICODE 0
+#endif
+
+#if PY_LITTLE_ENDIAN
+#define NATIVE_BYTEORDER -1
+#else
+#define NATIVE_BYTEORDER 1
+#endif
+
#ifdef MS_WINDOWS
#include <conio.h>
#define WAIT_FOR_STDIN
@@ -290,7 +308,6 @@ typedef struct {
} TkappObject;
#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
-#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
(void *) v, Py_REFCNT(v)))
@@ -311,10 +328,16 @@ static int tk_load_failed = 0;
#endif
+static PyObject *Tkapp_UnicodeResult(TkappObject *);
+
static PyObject *
-Tkinter_Error(PyObject *v)
+Tkinter_Error(TkappObject *self)
{
- PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
+ PyObject *res = Tkapp_UnicodeResult(self);
+ if (res != NULL) {
+ PyErr_SetObject(Tkinter_TclError, res);
+ Py_DECREF(res);
+ }
return NULL;
}
@@ -368,30 +391,35 @@ 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) {
- PyErr_NoMemory();
- return NULL;
- }
- while (s != e) {
- if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
- *q++ = '\0';
- s += 2;
- }
- else
- *q++ = *s++;
+ if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
+ return r;
+ }
+
+ char *buf = NULL;
+ PyErr_Clear();
+ /* Tcl encodes null character as \xc0\x80 */
+ if (memchr(s, '\xc0', size)) {
+ char *q;
+ const char *e = s + size;
+ q = buf = (char *)PyMem_Malloc(size);
+ if (buf == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ while (s != e) {
+ if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
+ *q++ = '\0';
+ s += 2;
}
- s = buf;
- size = q - s;
- r = PyUnicode_DecodeUTF8(s, size, NULL);
- PyMem_Free(buf);
+ else
+ *q++ = *s++;
}
+ s = buf;
+ size = q - s;
+ }
+ r = PyUnicode_DecodeUTF8(s, size, "surrogateescape");
+ if (buf != NULL) {
+ PyMem_Free(buf);
}
return r;
}
@@ -406,8 +434,21 @@ static PyObject *
unicodeFromTclObj(Tcl_Obj *value)
{
int len;
- char *s = Tcl_GetStringFromObj(value, &len);
+#if USE_TCL_UNICODE
+ int byteorder = NATIVE_BYTEORDER;
+ const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len);
+ if (sizeof(Tcl_UniChar) == 2)
+ return PyUnicode_DecodeUTF16((const char *)u, len * 2,
+ "surrogatepass", &byteorder);
+ else if (sizeof(Tcl_UniChar) == 4)
+ return PyUnicode_DecodeUTF32((const char *)u, len * 4,
+ "surrogatepass", &byteorder);
+ else
+ Py_UNREACHABLE();
+#else
+ const char *s = Tcl_GetStringFromObj(value, &len);
return unicodeFromTclStringAndSize(s, len);
+#endif
}
@@ -746,7 +787,7 @@ Tkapp_New(const char *screenName, const char *className,
#endif
if (Tcl_AppInit(v->interp) != TCL_OK) {
- PyObject *result = Tkinter_Error((PyObject *)v);
+ PyObject *result = Tkinter_Error(v);
#ifdef TKINTER_PROTECT_LOADTK
if (wantTk) {
const char *_tkinter_tk_failed;
@@ -817,12 +858,6 @@ PyTclObject_dealloc(PyTclObject *self)
Py_DECREF(tp);
}
-static const char *
-PyTclObject_TclString(PyObject *self)
-{
- return Tcl_GetString(((PyTclObject*)self)->value);
-}
-
/* Like _str, but create Unicode if necessary. */
PyDoc_STRVAR(PyTclObject_string__doc__,
"the string representation of this object, either as str or bytes");
@@ -1048,53 +1083,51 @@ AsObj(PyObject *value)
}
if (PyUnicode_Check(value)) {
- void *inbuf;
- Py_ssize_t size;
- int kind;
- Tcl_UniChar *outbuf = NULL;
- Py_ssize_t i;
- size_t allocsize;
-
if (PyUnicode_READY(value) == -1)
return NULL;
- inbuf = PyUnicode_DATA(value);
- size = PyUnicode_GET_LENGTH(value);
- if (size == 0)
- return Tcl_NewUnicodeObj((const void *)"", 0);
+ Py_ssize_t size = PyUnicode_GET_LENGTH(value);
+ if (size == 0) {
+ return Tcl_NewStringObj("", 0);
+ }
if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
PyErr_SetString(PyExc_OverflowError, "string is too long");
return NULL;
}
- kind = PyUnicode_KIND(value);
- if (kind == sizeof(Tcl_UniChar))
- return Tcl_NewUnicodeObj(inbuf, (int)size);
- allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
- outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize);
- /* Else overflow occurred, and we take the next exit */
- if (!outbuf) {
- PyErr_NoMemory();
- return NULL;
+ if (PyUnicode_IS_ASCII(value)) {
+ return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
+ (int)size);
}
- for (i = 0; i < size; i++) {
- Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
- /* We cannot test for sizeof(Tcl_UniChar) directly,
- so we test for UTF-8 size instead. */
-#if TCL_UTF_MAX == 3
- if (ch >= 0x10000) {
- /* Tcl doesn't do UTF-16, yet. */
- PyErr_Format(Tkinter_TclError,
- "character U+%x is above the range "
- "(U+0000-U+FFFF) allowed by Tcl",
- ch);
- PyMem_Free(outbuf);
- return NULL;
- }
+
+ PyObject *encoded;
+#if USE_TCL_UNICODE
+ if (sizeof(Tcl_UniChar) == 2)
+ encoded = _PyUnicode_EncodeUTF16(value,
+ "surrogatepass", NATIVE_BYTEORDER);
+ else if (sizeof(Tcl_UniChar) == 4)
+ encoded = _PyUnicode_EncodeUTF32(value,
+ "surrogatepass", NATIVE_BYTEORDER);
+ else
+ Py_UNREACHABLE();
+#else
+ encoded = _PyUnicode_AsUTF8String(value, "surrogateescape");
#endif
- outbuf[i] = ch;
+ if (!encoded) {
+ return NULL;
}
- result = Tcl_NewUnicodeObj(outbuf, (int)size);
- PyMem_Free(outbuf);
+ size = PyBytes_GET_SIZE(encoded);
+ if (size > INT_MAX) {
+ Py_DECREF(encoded);
+ PyErr_SetString(PyExc_OverflowError, "string is too long");
+ return NULL;
+ }
+#if USE_TCL_UNICODE
+ result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded),
+ (int)(size / sizeof(Tcl_UniChar)));
+#else
+ result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size);
+#endif
+ Py_DECREF(encoded);
return result;
}
@@ -1113,7 +1146,7 @@ AsObj(PyObject *value)
}
static PyObject *
-fromBoolean(PyObject* tkapp, Tcl_Obj *value)
+fromBoolean(TkappObject *tkapp, Tcl_Obj *value)
{
int boolValue;
if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
@@ -1122,7 +1155,7 @@ fromBoolean(PyObject* tkapp, Tcl_Obj *value)
}
static PyObject*
-fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
+fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value)
{
Tcl_WideInt wideValue;
if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
@@ -1138,7 +1171,7 @@ fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
#ifdef HAVE_LIBTOMMAMTH
static PyObject*
-fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
+fromBignumObj(TkappObject *tkapp, Tcl_Obj *value)
{
mp_int bigValue;
unsigned long numBytes;
@@ -1174,32 +1207,31 @@ fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
#endif
static PyObject*
-FromObj(PyObject* tkapp, Tcl_Obj *value)
+FromObj(TkappObject *tkapp, Tcl_Obj *value)
{
PyObject *result = NULL;
- TkappObject *app = (TkappObject*)tkapp;
Tcl_Interp *interp = Tkapp_Interp(tkapp);
if (value->typePtr == NULL) {
- return unicodeFromTclStringAndSize(value->bytes, value->length);
+ return unicodeFromTclObj(value);
}
- if (value->typePtr == app->BooleanType ||
- value->typePtr == app->OldBooleanType) {
+ if (value->typePtr == tkapp->BooleanType ||
+ value->typePtr == tkapp->OldBooleanType) {
return fromBoolean(tkapp, value);
}
- if (value->typePtr == app->ByteArrayType) {
+ if (value->typePtr == tkapp->ByteArrayType) {
int size;
char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
return PyBytes_FromStringAndSize(data, size);
}
- if (value->typePtr == app->DoubleType) {
+ if (value->typePtr == tkapp->DoubleType) {
return PyFloat_FromDouble(value->internalRep.doubleValue);
}
- if (value->typePtr == app->IntType) {
+ if (value->typePtr == tkapp->IntType) {
long longValue;
if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
return PyLong_FromLong(longValue);
@@ -1207,8 +1239,8 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
fall through to wideInt handling. */
}
- if (value->typePtr == app->IntType ||
- value->typePtr == app->WideIntType) {
+ if (value->typePtr == tkapp->IntType ||
+ value->typePtr == tkapp->WideIntType) {
result = fromWideIntObj(tkapp, value);
if (result != NULL || PyErr_Occurred())
return result;
@@ -1218,14 +1250,14 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
}
#ifdef HAVE_LIBTOMMAMTH
- if (value->typePtr == app->IntType ||
- value->typePtr == app->WideIntType ||
- value->typePtr == app->BignumType) {
+ if (value->typePtr == tkapp->IntType ||
+ value->typePtr == tkapp->WideIntType ||
+ value->typePtr == tkapp->BignumType) {
return fromBignumObj(tkapp, value);
}
#endif
- if (value->typePtr == app->ListType) {
+ if (value->typePtr == tkapp->ListType) {
int size;
int i, status;
PyObject *elem;
@@ -1253,30 +1285,28 @@ FromObj(PyObject* tkapp, Tcl_Obj *value)
return result;
}
- if (value->typePtr == app->ProcBodyType) {
+ if (value->typePtr == tkapp->ProcBodyType) {
/* fall through: return tcl object. */
}
- if (value->typePtr == app->StringType) {
- return PyUnicode_FromKindAndData(
- sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
- Tcl_GetCharLength(value));
+ if (value->typePtr == tkapp->StringType) {
+ return unicodeFromTclObj(value);
}
#if TK_HEX_VERSION >= 0x08050000
- if (app->BooleanType == NULL &&
+ if (tkapp->BooleanType == NULL &&
strcmp(value->typePtr->name, "booleanString") == 0) {
/* booleanString type is not registered in Tcl */
- app->BooleanType = value->typePtr;
+ tkapp->BooleanType = value->typePtr;
return fromBoolean(tkapp, value);
}
#endif
#ifdef HAVE_LIBTOMMAMTH
- if (app->BignumType == NULL &&
+ if (tkapp->BignumType == NULL &&
strcmp(value->typePtr->name, "bignum") == 0) {
/* bignum type is not registered in Tcl */
- app->BignumType = value->typePtr;
+ tkapp->BignumType = value->typePtr;
return fromBignumObj(tkapp, value);
}
#endif
@@ -1366,19 +1396,28 @@ finally:
return NULL;
}
+/* Convert the results of a command call into a Python string. */
+
+static PyObject *
+Tkapp_UnicodeResult(TkappObject *self)
+{
+ return unicodeFromTclObj(Tcl_GetObjResult(self->interp));
+}
+
+
/* Convert the results of a command call into a Python objects. */
-static PyObject*
-Tkapp_CallResult(TkappObject *self)
+static PyObject *
+Tkapp_ObjectResult(TkappObject *self)
{
PyObject *res = NULL;
Tcl_Obj *value = Tcl_GetObjResult(self->interp);
- if(self->wantobjects) {
+ if (self->wantobjects) {
/* Not sure whether the IncrRef is necessary, but something
may overwrite the interpreter result while we are
converting it. */
Tcl_IncrRefCount(value);
- res = FromObj((PyObject*)self, value);
+ res = FromObj(self, value);
Tcl_DecrRefCount(value);
} else {
res = unicodeFromTclObj(value);
@@ -1410,15 +1449,13 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
ENTER_PYTHON
if (i == TCL_ERROR) {
- *(e->res) = NULL;
- *(e->exc_type) = NULL;
- *(e->exc_tb) = NULL;
- *(e->exc_value) = PyObject_CallFunction(
- Tkinter_TclError, "s",
- Tcl_GetStringResult(e->self->interp));
+ *(e->res) = Tkinter_Error(e->self);
}
else {
- *(e->res) = Tkapp_CallResult(e->self);
+ *(e->res) = Tkapp_ObjectResult(e->self);
+ }
+ if (*(e->res) == NULL) {
+ PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
}
LEAVE_PYTHON
@@ -1506,9 +1543,9 @@ Tkapp_Call(PyObject *selfptr, PyObject *args)
ENTER_OVERLAP
if (i == TCL_ERROR)
- Tkinter_Error(selfptr);
+ Tkinter_Error(self);
else
- res = Tkapp_CallResult(self);
+ res = Tkapp_ObjectResult(self);
LEAVE_OVERLAP_TCL
@@ -1540,9 +1577,9 @@ _tkinter_tkapp_eval_impl(TkappObject *self, const char *script)
err = Tcl_Eval(Tkapp_Interp(self), script);
ENTER_OVERLAP
if (err == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
- res = unicodeFromTclString(Tkapp_Result(self));
+ res = Tkapp_UnicodeResult(self);
LEAVE_OVERLAP_TCL
return res;
}
@@ -1569,9 +1606,9 @@ _tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName)
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
ENTER_OVERLAP
if (err == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
- res = unicodeFromTclString(Tkapp_Result(self));
+ res = Tkapp_UnicodeResult(self);
LEAVE_OVERLAP_TCL
return res;
}
@@ -1598,9 +1635,9 @@ _tkinter_tkapp_record_impl(TkappObject *self, const char *script)
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
ENTER_OVERLAP
if (err == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
- res = unicodeFromTclString(Tkapp_Result(self));
+ res = Tkapp_UnicodeResult(self);
LEAVE_OVERLAP_TCL
return res;
}
@@ -1631,13 +1668,13 @@ _tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg)
/** Tcl Variable **/
-typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
+typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int);
TCL_DECLARE_MUTEX(var_mutex)
typedef struct VarEvent {
Tcl_Event ev; /* must be first */
- PyObject *self;
+ TkappObject *self;
PyObject *args;
int flags;
EventFunc func;
@@ -1692,7 +1729,7 @@ varname_converter(PyObject *in, void *_out)
return 1;
}
if (PyTclObject_Check(in)) {
- *out = PyTclObject_TclString(in);
+ *out = Tcl_GetString(((PyTclObject *)in)->value);
return 1;
}
PyErr_Format(PyExc_TypeError,
@@ -1750,7 +1787,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
PyErr_NoMemory();
return NULL;
}
- ev->self = selfptr;
+ ev->self = self;
ev->args = args;
ev->flags = flags;
ev->func = func;
@@ -1770,11 +1807,11 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
return res;
}
/* Tcl is not threaded, or this is the interpreter thread. */
- return func(selfptr, args, flags);
+ return func(self, args, flags);
}
static PyObject *
-SetVar(PyObject *self, PyObject *args, int flags)
+SetVar(TkappObject *self, PyObject *args, int flags)
{
const char *name1, *name2;
PyObject *newValue;
@@ -1843,7 +1880,7 @@ Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
static PyObject *
-GetVar(PyObject *self, PyObject *args, int flags)
+GetVar(TkappObject *self, PyObject *args, int flags)
{
const char *name1, *name2=NULL;
PyObject *res = NULL;
@@ -1858,10 +1895,9 @@ GetVar(PyObject *self, PyObject *args, int flags)
tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
ENTER_OVERLAP
if (tres == NULL) {
- PyErr_SetString(Tkinter_TclError,
- Tcl_GetStringResult(Tkapp_Interp(self)));
+ Tkinter_Error(self);
} else {
- if (((TkappObject*)self)->wantobjects) {
+ if (self->wantobjects) {
res = FromObj(self, tres);
}
else {
@@ -1887,7 +1923,7 @@ Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
static PyObject *
-UnsetVar(PyObject *self, PyObject *args, int flags)
+UnsetVar(TkappObject *self, PyObject *args, int flags)
{
char *name1, *name2=NULL;
int code;
@@ -1959,7 +1995,7 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
CHECK_STRING_LENGTH(s);
value = Tcl_NewStringObj(s, -1);
if (value == NULL)
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
}
/* Don't use Tcl_GetInt() because it returns ambiguous result for value
in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
@@ -1968,14 +2004,14 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg)
value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
*/
#ifdef HAVE_LIBTOMMAMTH
- result = fromBignumObj((PyObject *)self, value);
+ result = fromBignumObj(self, value);
#else
- result = fromWideIntObj((PyObject *)self, value);
+ result = fromWideIntObj(self, value);
#endif
Tcl_DecrRefCount(value);
if (result != NULL || PyErr_Occurred())
return result;
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
}
/*[clinic input]
@@ -2006,7 +2042,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
if (Tcl_GetDoubleFromObj(Tkapp_Interp(self),
((PyTclObject*)arg)->value,
&v) == TCL_ERROR)
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
return PyFloat_FromDouble(v);
}
@@ -2014,7 +2050,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg)
return NULL;
CHECK_STRING_LENGTH(s);
if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
return PyFloat_FromDouble(v);
}
@@ -2041,7 +2077,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
((PyTclObject*)arg)->value,
&v) == TCL_ERROR)
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
return PyBool_FromLong(v);
}
@@ -2049,7 +2085,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg)
return NULL;
CHECK_STRING_LENGTH(s);
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
return PyBool_FromLong(v);
}
@@ -2075,9 +2111,9 @@ _tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s)
retval = Tcl_ExprString(Tkapp_Interp(self), s);
ENTER_OVERLAP
if (retval == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
- res = unicodeFromTclString(Tkapp_Result(self));
+ res = Tkapp_UnicodeResult(self);
LEAVE_OVERLAP_TCL
return res;
}
@@ -2105,7 +2141,7 @@ _tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s)
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
ENTER_OVERLAP
if (retval == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
res = PyLong_FromLong(v);
LEAVE_OVERLAP_TCL
@@ -2136,7 +2172,7 @@ _tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s)
ENTER_OVERLAP
PyFPE_END_PROTECT(retval)
if (retval == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
res = PyFloat_FromDouble(v);
LEAVE_OVERLAP_TCL
@@ -2165,7 +2201,7 @@ _tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s)
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
ENTER_OVERLAP
if (retval == TCL_ERROR)
- res = Tkinter_Error((PyObject *)self);
+ res = Tkinter_Error(self);
else
res = PyLong_FromLong(v);
LEAVE_OVERLAP_TCL
@@ -2198,12 +2234,12 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
if (Tcl_ListObjGetElements(Tkapp_Interp(self),
((PyTclObject*)arg)->value,
&objc, &objv) == TCL_ERROR) {
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
}
if (!(v = PyTuple_New(objc)))
return NULL;
for (i = 0; i < objc; i++) {
- PyObject *s = FromObj((PyObject*)self, objv[i]);
+ PyObject *s = FromObj(self, objv[i]);
if (!s) {
Py_DECREF(v);
return NULL;
@@ -2231,7 +2267,7 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg)
if (Tcl_SplitList(Tkapp_Interp(self), list,
&argc, &argv) == TCL_ERROR) {
PyMem_Free(list);
- return Tkinter_Error((PyObject *)self);
+ return Tkinter_Error(self);
}
if (!(v = PyTuple_New(argc)))
@@ -2275,16 +2311,16 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg)
int i;
if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
&objc, &objv) == TCL_ERROR) {
- return FromObj((PyObject*)self, value);
+ return FromObj(self, value);
}
if (objc == 0)
return PyUnicode_FromString("");
if (objc == 1)
- return FromObj((PyObject*)self, objv[0]);
+ return FromObj(self, objv[0]);
if (!(v = PyTuple_New(objc)))
return NULL;
for (i = 0; i < objc; i++) {
- PyObject *s = FromObj((PyObject*)self, objv[i]);
+ PyObject *s = FromObj(self, objv[i]);
if (!s) {
Py_DECREF(v);
return NULL;
@@ -2331,34 +2367,31 @@ PythonCmd_Error(Tcl_Interp *interp)
* function or method.
*/
static int
-PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[])
+PythonCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
{
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
- PyObject *func, *arg, *res;
- int i, rv;
+ PyObject *args, *res;
+ int i;
Tcl_Obj *obj_res;
ENTER_PYTHON
- /* TBD: no error checking here since we know, via the
- * Tkapp_CreateCommand() that the client data is a two-tuple
- */
- func = data->func;
-
- /* Create argument list (argv1, ..., argvN) */
- if (!(arg = PyTuple_New(argc - 1)))
+ /* Create argument tuple (objv1, ..., objvN) */
+ if (!(args = PyTuple_New(objc - 1)))
return PythonCmd_Error(interp);
- for (i = 0; i < (argc - 1); i++) {
- PyObject *s = unicodeFromTclString(argv[i + 1]);
+ for (i = 0; i < (objc - 1); i++) {
+ PyObject *s = unicodeFromTclObj(objv[i + 1]);
if (!s) {
- Py_DECREF(arg);
+ Py_DECREF(args);
return PythonCmd_Error(interp);
}
- PyTuple_SET_ITEM(arg, i, s);
+ PyTuple_SET_ITEM(args, i, s);
}
- res = PyObject_Call(func, arg, NULL);
- Py_DECREF(arg);
+
+ res = PyObject_Call(data->func, args, NULL);
+ Py_DECREF(args);
if (res == NULL)
return PythonCmd_Error(interp);
@@ -2368,18 +2401,15 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[
Py_DECREF(res);
return PythonCmd_Error(interp);
}
- else {
- Tcl_SetObjResult(interp, obj_res);
- rv = TCL_OK;
- }
-
+ Tcl_SetObjResult(interp, obj_res);
Py_DECREF(res);
LEAVE_PYTHON
- return rv;
+ return TCL_OK;
}
+
static void
PythonCmdDelete(ClientData clientData)
{
@@ -2411,7 +2441,7 @@ static int
Tkapp_CommandProc(CommandEvent *ev, int flags)
{
if (ev->create)
- *ev->status = Tcl_CreateCommand(
+ *ev->status = Tcl_CreateObjCommand(
ev->interp, ev->name, PythonCmd,
ev->data, PythonCmdDelete) == NULL;
else
@@ -2477,7 +2507,7 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name,
else
{
ENTER_TCL
- err = Tcl_CreateCommand(
+ err = Tcl_CreateObjCommand(
Tkapp_Interp(self), name, PythonCmd,
(ClientData)data, PythonCmdDelete) == NULL;
LEAVE_TCL
@@ -2953,9 +2983,9 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
if (err == TCL_ERROR) {
/* This sets an exception, but we cannot return right
away because we need to exit the overlap first. */
- Tkinter_Error((PyObject *)self);
+ Tkinter_Error(self);
} else {
- _tk_exists = Tkapp_Result(self);
+ _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self));
}
LEAVE_OVERLAP_TCL
if (err == TCL_ERROR) {
@@ -2963,8 +2993,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
}
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
if (Tk_Init(interp) == TCL_ERROR) {
- PyErr_SetString(Tkinter_TclError,
- Tcl_GetStringResult(Tkapp_Interp(self)));
+ Tkinter_Error(self);
#ifdef TKINTER_PROTECT_LOADTK
tk_load_failed = 1;
#endif