Serhiy Storchaka <storchaka+cpyt...@gmail.com> added the comment:

Thank you for your examples Pat. Now it looks clearer to me.

Semantically this data in Tk is a sequence of pairs: states (which can be a 
single word or several words or empty) and default value.

>>> from tkinter import ttk
>>> style = ttk.Style()
>>> style.theme_use('clam')
>>> style.tk.eval(f'{style._name} map TCombobox -fieldbackground')
'{readonly focus} #4a6984 readonly #dcdad5'
>>> style.tk.eval(f'{style._name} map TNotebook.Tab -background')
'selected #dcdad5 {} #bab5ab'

Internally states represented in Tk as the StateSpec object. When automatically 
convert to Python it became the Tcl_Obj object with typename 'StateSpec'. 
Without postprocessing.

>>> style.tk.call(style._name, 'map', 'TCombobox', '-fieldbackground')
(<StateSpec object: 'readonly focus'>, '#4a6984', <StateSpec object: 
'readonly'>, '#dcdad5')
>>> style.tk.call(style._name, 'map', 'TNotebook.Tab', '-background')
(<StateSpec object: 'selected'>, '#dcdad5', <StateSpec object: ''>, '#bab5ab')

Style.map() does postprocessing. It converts a sequence (with even items 
number) to a list of tuples. The last item of a tuple is the default value, and 
the rest are items of the StateSpec object.

>>> style.map('TCombobox', 'fieldbackground')
[('readonly', 'focus', '#4a6984'), ('readonly', '#dcdad5')]
>>> style.map('TNotebook.Tab', 'background')
[('selected', '#dcdad5'), ('#bab5ab',)]

But when set tkinter.wantobjects = 0 before running this example the result 
will be different, because StateSpec objects will be automatically represented 
as strings (it matches the behavior of initial versions of Tkinter):

>>> style.tk.call(style._name, 'map', 'TCombobox', '-fieldbackground')
'{readonly focus} #4a6984 readonly #dcdad5'
>>> style.tk.call(style._name, 'map', 'TNotebook.Tab', '-background')
'selected #dcdad5 {} #bab5ab'
>>> style.map('TCombobox', 'fieldbackground')
[('readonly focus', '#4a6984'), ('readonly', '#dcdad5')]
>>> style.map('TNotebook.Tab', 'background')
[('selected', '#dcdad5'), ('', '#bab5ab')]

The main problem is in representing an empty StateSpec. As every string in 
Python contains an empty string, {} can represent an empty sequence and a 
sequence containing single empty string. In Python, it can be no items before 
default value (like in ('#bab5ab',)) or a single item containing an empty 
string (like in ('', '#bab5ab')).

The former representation (an empty sequence) is default for the style.map() 
output, but it is rejected as the style.map() input (see state[0] in 
_mapdict_values). There are two ways to fix it: either change the output of 
style.map() (what PR 23241 does) or change the validation of the input. I think 
that the latter solution can be backported, but the former can be used only in 
the future Python version.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue42328>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to