This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ttk.Treeview: _tkinter.TclError: list element in quotes followed by ";" instead of space
Type: behavior Stage: resolved
Components: Tkinter Versions: Python 3.7, Python 2.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: serhiy.storchaka Nosy List: kumba, serhiy.storchaka, terry.reedy
Priority: normal Keywords:

Created on 2017-12-14 21:35 by kumba, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (6)
msg308340 - (view) Author: Joshua Kinard (kumba) Date: 2017-12-14 21:35
I think I've found another bug with Tkinter's string handling in Python 2.7.14, before it passes off to the TCL interpreter when inserting items into a ttk.Treeview widget.  Specifically, it doesn't handle strings containing semi-colons very well if they are passed in via a kwarg dict.

Below is a simple test case.  The "kw" variable has a 'values' key with a string value using single quotes to store the value '" ";':

-------------------------------------------------------------------------------
from Tkinter import *
from ttk import *

root = Tk()
tv = Treeview(root, columns=("foobar",))

tv.heading("foobar", text="Foobar!")
tv.column("#0", width=0)
tv.column("foobar", stretch=True, minwidth=100, width=400)
tv.grid()

kw = {'values': '" ";', 'tags': ''}
tv.insert("", END, iid=None, **kw)

root.mainloop()
-------------------------------------------------------------------------------

This sample triggers this traceback:

Traceback (most recent call last):
  File "test.py", line 14, in <module>
    tv.insert("", END, iid=None, **kw)
  File "C:\Python27\lib\lib-tk\ttk.py", line 1339, in insert
    res = self.tk.call(self._w, "insert", parent, index, *opts)
_tkinter.TclError: list element in quotes followed by ";" instead of space


Furthermore, if the 'values' key is changed to the string 'X:"Y ";', you trigger a different traceback:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    tv.insert("", END, iid=None, **kw)
  File "C:\Python27\lib\lib-tk\ttk.py", line 1339, in insert
    res = self.tk.call(self._w, "insert", parent, index, *opts)
_tkinter.TclError: unmatched open quote in list

So definitely a case of something in the parser not handling things properly before sending to the TCL interpreter.

I suspect this is similar to Issue #15861.  One can work around this bug by checking for either a whitespace or backslash character in the string, and wrapping the string in curly braces if so, to disable TCL substitution mechanism, and it'll insert the string and display it correctly in the widget.

I have only verified this in Python 2.7.14 at the moment, which is what I primarily work in right now.
msg308456 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2017-12-16 05:23
With imports modified, same exceptions in 3.7.0a2 on Win10
msg313867 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-15 10:07
According to the documentation (https://www.tcl.tk/man/tcl/TkCmd/ttk_treeview.htm) the item option "values" is "The list of values associated with the item.", and the item option "tags" is "A list of tags associated with this item." Tcl's list corresponds Python's tuple (lists are also accepted in Python 3).

Change your example to:

    kw = {'values': ('" ";',), 'tags': ()}
msg313893 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2018-03-15 16:31
Our ttk doc, https://docs.python.org/3/library/tkinter.ttk.html#item-options, here copies the tk doc: "The list of values associated with the item."  It should say 'tuple or list', but that is a generic (and separate) issue of our ttk doc not translating '(tcl) list' to '(python) sequence' or '(python) tuple or list'.

The NMT doc, http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-Treeview.html, is unnecessarily vague ('data items') about what needs to be passed for values.  It correctly notes that a single string is accepted for tags, but I don't know that this is guaranteed.
msg313935 - (view) Author: Joshua Kinard (kumba) Date: 2018-03-16 07:37
I have to disagree rather strongly with closing this as "not a bug".  If the issue really boils down to incorrectly passing a single string when there is only one item in 'values', and a single-item tuple should be used instead, then shouldn't the better solution be for Python to handle this automatically and re-cast the errant string into a tuple?

My example indicates a case of where I got the Tcl interpreter itself to choke on invalid user input.  Even though the tkinter binding module catches the exception from the Tcl interpreter, I think it's Python's job as the wrapping language to catch any user stupidity done in Python and try to work around it if it's simple to do so.  A user coding against Tkinter/Ttk should not be required to have or need knowledge of Tcl/Tk itself to code a GUI.  That knowledge certainly helps, but not having it is one of Python's selling points for using Tkinter in the first place.

I have a coding project where I initially tripped up the semi-colon issue while parsing data from a text file into a Treeview widget (in listbox mode), that has a single-column.  The data being parsed included quoted regular expression syntax.  The function doing the parsing passed the parsed data to another function that populated the Treeview using **kwargs to send "values" and "tags" to Treeview's "insert" method.  It was a backslash character in the quoted regular expression string, at a point before the semi-colon, that eventually goofed the Tcl interpreter up, but //only// when passed in via **kwargs syntax.

The original code was too complex to replicate for the bug, so I reduced things down to a smaller testcase.  During this, I inadvertently tripped up the other bug with the unmatched open quote error, so I reported both.

My current workaround involves scanning the input for a backslash character or a whitespace character (which also trips things up), and if found, wrap the string in curly braces, which disables Tcl's substitution mechanism for that string, then calling Treeview's "insert" method.  It's more complicated this way, but safe for dealing with regular expression strings as possible input.
msg313943 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-03-16 09:24
> If the issue really boils down to incorrectly passing a single string when there is only one item in 'values', and a single-item tuple should be used instead, then shouldn't the better solution be for Python to handle this automatically and re-cast the errant string into a tuple?

Tkinter is rather a thin wrapper around Tcl/Tk. I just passes values to Tcl. Tcl is a weak typed language. Internally it can use different types for performance, but semantically all are strings. "a b" is a string and a 2-element list, and a 1-element dict at the same time. It is Tcl try to re-cast the errant string into a Tcl list, and fails because it has incorrect syntax. Python can't know your intention. It supposes that you know what you do. If under re-casting you meant passing a string to a tuple constructor, `tuple(values)`, this will be obviously wrong. If your meant parsing a string to a tuple at Python side -- it will file as well as parsing it at Tcl side. If you meant wrapping a string into a one-element tuple, `(values,)`, this can break working code when a user intentionally passes a space separated list of words:

    tv.insert("", END, values=(foo, bar), tags="foo bar")

Additionally, any special cases will complicate the code of Tkinter (currently it is rather a thin wrapper) and complicate the mental model.
History
Date User Action Args
2022-04-11 14:58:55adminsetgithub: 76509
2018-03-16 09:24:26serhiy.storchakasetmessages: + msg313943
2018-03-16 07:37:03kumbasetmessages: + msg313935
2018-03-15 16:31:10terry.reedysetstatus: open -> closed
resolution: not a bug
messages: + msg313893

stage: resolved
2018-03-15 10:07:59serhiy.storchakasetmessages: + msg313867
2017-12-16 05:23:01terry.reedysetnosy: + terry.reedy

messages: + msg308456
versions: + Python 3.7
2017-12-14 21:40:15serhiy.storchakasetassignee: serhiy.storchaka

nosy: + serhiy.storchaka
2017-12-14 21:35:04kumbacreate