mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
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).
This commit is contained in:
parent
2290b23dfc
commit
06cb94bc84
9 changed files with 241 additions and 242 deletions
|
@ -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++;
|
||||
}
|
||||
s = buf;
|
||||
size = q - s;
|
||||
r = PyUnicode_DecodeUTF8(s, size, NULL);
|
||||
PyMem_Free(buf);
|
||||
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;
|
||||
}
|
||||
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();
|
||||
if (PyUnicode_IS_ASCII(value)) {
|
||||
return Tcl_NewStringObj((const char *)PyUnicode_DATA(value),
|
||||
(int)size);
|
||||
}
|
||||
|
||||
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
|
||||
if (!encoded) {
|
||||
return NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
outbuf[i] = ch;
|
||||
size = PyBytes_GET_SIZE(encoded);
|
||||
if (size > INT_MAX) {
|
||||
Py_DECREF(encoded);
|
||||
PyErr_SetString(PyExc_OverflowError, "string is too long");
|
||||
return NULL;
|
||||
}
|
||||
result = Tcl_NewUnicodeObj(outbuf, (int)size);
|
||||
PyMem_Free(outbuf);
|
||||
#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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue