summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2003-01-04 00:08:09 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2003-01-04 00:08:09 (GMT)
commit25c7b50e8f5c8bcdda6631a5d3042eb3ae460b2c (patch)
tree78f27fe05109377ac44a1a0d5c400542bc9b4180
parent77023048854bc408308a10dc092bbd216f9da45e (diff)
downloadcpython-25c7b50e8f5c8bcdda6631a5d3042eb3ae460b2c.zip
cpython-25c7b50e8f5c8bcdda6631a5d3042eb3ae460b2c.tar.gz
cpython-25c7b50e8f5c8bcdda6631a5d3042eb3ae460b2c.tar.bz2
Convert Tcl path objects to strings. Fixes #661357.
Provide .string attribute and __unicode for Tcl_Objs.
-rw-r--r--Lib/lib-tk/tkFileDialog.py6
-rw-r--r--Modules/_tkinter.c65
2 files changed, 70 insertions, 1 deletions
diff --git a/Lib/lib-tk/tkFileDialog.py b/Lib/lib-tk/tkFileDialog.py
index 569254a..63487d2 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 212bbad..d6407e2 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*/