From 25c7b50e8f5c8bcdda6631a5d3042eb3ae460b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sat, 4 Jan 2003 00:08:09 +0000 Subject: [PATCH] Convert Tcl path objects to strings. Fixes #661357. Provide .string attribute and __unicode for Tcl_Objs. --- Lib/lib-tk/tkFileDialog.py | 6 ++++ Modules/_tkinter.c | 65 +++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/Lib/lib-tk/tkFileDialog.py b/Lib/lib-tk/tkFileDialog.py index 569254a4565..63487d2037b 100644 --- a/Lib/lib-tk/tkFileDialog.py +++ b/Lib/lib-tk/tkFileDialog.py @@ -55,6 +55,12 @@ class _Dialog(Dialog): if result: # keep directory and filename until next time import os + # convert Tcl path objects to strings + try: + result = result.string + except AttributeError: + # it already is a string + pass path, file = os.path.split(result) self.options["initialdir"] = path self.options["initialfile"] = file diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 212bbadf19b..d6407e26cfb 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -684,6 +684,7 @@ Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev, typedef struct { PyObject_HEAD Tcl_Obj *value; + PyObject *string; /* This cannot cause cycles. */ } PyTclObject; staticforward PyTypeObject PyTclObject_Type; @@ -698,6 +699,7 @@ newPyTclObject(Tcl_Obj *arg) return NULL; Tcl_IncrRefCount(arg); self->value = arg; + self->string = NULL; return (PyObject*)self; } @@ -705,15 +707,69 @@ static void PyTclObject_dealloc(PyTclObject *self) { Tcl_DecrRefCount(self->value); + Py_XDECREF(self->string); PyObject_Del(self); } static PyObject * PyTclObject_str(PyTclObject *self) { + if (self->string && PyString_Check(self->string)) { + Py_INCREF(self->string); + return self->string; + } + /* XXX Could cache value if it is an ASCII string. */ return PyString_FromString(Tcl_GetString(self->value)); } +/* Like _str, but create Unicode if necessary. */ +static PyObject * +PyTclObject_string(PyTclObject *self, void *ignored) +{ + char *s; + int i, len; + if (!self->string) { + s = Tcl_GetStringFromObj(self->value, &len); + for (i = 0; i < len; i++) + if (s[i] & 0x80) + break; +#ifdef Py_USING_UNICODE + if (i == len) + /* It is an ASCII string. */ + self->string = PyString_FromStringAndSize(s, len); + else { + self->string = PyUnicode_DecodeUTF8(s, len, "strict"); + if (!self->string) { + PyErr_Clear(); + self->string = PyString_FromStringAndSize(s, len); + } + } +#else + self->string = PyString_FromStringAndSize(s, len); +#endif + if (!self->string) + return NULL; + } + Py_INCREF(self->string); + return self->string; +} + +#ifdef Py_USING_UNICODE +static PyObject * +PyTclObject_unicode(PyTclObject *self, void *ignored) +{ + char *s; + int len; + if (self->string && PyUnicode_Check(self->string)) { + Py_INCREF(self->string); + return self->string; + } + /* XXX Could chache result if it is non-ASCII. */ + s = Tcl_GetStringFromObj(self->value, &len); + return PyUnicode_DecodeUTF8(s, len, "strict"); +} +#endif + static PyObject * PyTclObject_repr(PyTclObject *self) { @@ -731,9 +787,16 @@ get_typename(PyTclObject* obj, void* ignored) static PyGetSetDef PyTclObject_getsetlist[] = { {"typename", (getter)get_typename, NULL, "name of the Tcl type"}, + {"string", (getter)PyTclObject_string, NULL, "name of the Tcl type"}, {0}, }; +static PyMethodDef PyTclObject_methods[] = { + {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS, + "convert argument to unicode"}, + {0} +}; + statichere PyTypeObject PyTclObject_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ @@ -764,7 +827,7 @@ statichere PyTypeObject PyTclObject_Type = { 0, /*tp_weaklistoffset*/ 0, /*tp_iter*/ 0, /*tp_iternext*/ - 0, /*tp_methods*/ + PyTclObject_methods, /*tp_methods*/ 0, /*tp_members*/ PyTclObject_getsetlist, /*tp_getset*/ 0, /*tp_base*/