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: Tkinter.Misc has no __contains__ method
Type: enhancement Stage:
Components: Tkinter Versions:
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: georg.brandl, gpolo, jepler, sbronson, tzot
Priority: normal Keywords:

Created on 2002-09-28 04:27 by sbronson, last changed 2022-04-10 16:05 by admin. This issue is now closed.

Messages (5)
msg12523 - (view) Author: Samuel Bronson (sbronson) Date: 2002-09-28 04:27
This can lead to a lot of confusion.

If I do `"spam" in widget', I get a TypeError.

Case in point: (the code in question is probably
incorrect, so I am not including it)

 /usr/tmp/python-14024DA 
   45             self.pack()
   46 
   47 if __name__ == '__main__':
   48     widget = TkLife(None, height=20, width=20)
   49     widget.loop()
widget undefined
TkLife = <class __main__.TkLife>
None undefined
height undefined
width undefined

 /usr/tmp/python-14024DA in
__init__(self=<__main__.TkLife instance>, master=None,
**kw={'height': 20, 'width': 20})
   27         self['state'] = Tkinter.DISABLED
   28 
   29         if 'cells' not in self:
   30             assert 'width' in self and 'height'
in self
   31             self['cells'] =
randomcells(self['width'], self['height'])
self = <__main__.TkLife instance>

 /usr/local/lib/python2.2/lib-tk/Tkinter.py in
cget(self=<__main__.TkLife instance>, key=0)
 1088     def cget(self, key):
 1089         """Return the resource value for a KEY
given as string."""
 1090         return self.tk.call(self._w, 'cget', '-'
+ key)
 1091     __getitem__ = cget
 1092     def __setitem__(self, key, value):
self = <__main__.TkLife instance>
self.tk = <tkapp object>
self.tk.call = <built-in method call of tkapp object>
self._w = '.135644212'
key = 0
TypeError: cannot concatenate 'str' and 'int' objects
      __doc__ =
'Inappropriate argument type.'
      __getitem__ =
<bound method TypeError.__getitem__ of
<exceptions.TypeError instance at 0x83202cc>>
      __init__ =
<bound method TypeError.__init__ of
<exceptions.TypeError instance at 0x83202cc>>
      __module__ =
'exceptions'
      __str__ =
<bound method TypeError.__str__ of
<exceptions.TypeError instance at 0x83202cc>>
      args =
("cannot concatenate 'str' and 'int' objects",)

The above is a description of an error in a Python
program.  Here is
the original traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/tmp/python-14024DA", line 48, in ?
    widget = TkLife(None, height=20, width=20)
  File "/usr/tmp/python-14024DA", line 29, in __init__
    if 'cells' not in self:
  File "/usr/local/lib/python2.2/lib-tk/Tkinter.py",
line 1090, in cget
    return self.tk.call(self._w, 'cget', '-' + key)
TypeError: cannot concatenate 'str' and 'int' objects
msg12524 - (view) Author: Jeff Epler (jepler) Date: 2002-09-29 13:52
Logged In: YES 
user_id=2772

This patch makes Tkinter widgets more "dict-like".  I don't
know if this is really desirable, I've never configured
widgets through the __setitem__ interface.

* __getitem__ raises KeyError when cget() raises TclError
* __setitem__ raises KeyError when configure() raises TclError
* implemented has_key(), __contains__(), values(), items()

Uh, I'm obviously blind here, because I don't see the
"attach file" section of the tracker.  Sorry, but I'll have
to inline the patch.  I'll also place it at
http://unpythonic.net/~jepler/tkinter-dictlike.diff

--- Tkinter.py.ori      Sun Sep 29 08:30:58 2002
+++ Tkinter.py  Sun Sep 29 08:46:20 2002
@@ -1096,13 +1096,27 @@
     def cget(self, key):
         """Return the resource value for a KEY given as
string."""
         return self.tk.call(self._w, 'cget', '-' + key)
-    __getitem__ = cget
+    def __getitem__(self, key):
+        try:
+            return self.cget(key)
+        except TclError:
+            raise KeyError, key
     def __setitem__(self, key, value):
-        self.configure({key: value})
+        try:
+            self.configure({key: value})
+        except TclError:
+            raise KeyError, key
+    def has_key(self, key):
+        return key in self.keys()
+    __contains__ = has_key
     def keys(self):
         """Return a list of all resource names of this
widget."""
         return map(lambda x: x[0][1:],
                self.tk.split(self.tk.call(self._w,
'configure')))
+    def values(self):
+        return [self[k] for k in self.keys()]
+    def items(self):
+        return [(k, self[k]) for k in self.keys()]
     def __str__(self):
         """Return the window path name of this widget."""
         return self._w
msg12525 - (view) Author: Χρήστος Γεωργίου (Christos Georgiou) (tzot) * Date: 2006-03-31 17:00
Logged In: YES 
user_id=539787

The __setitem__ and __getitem__ methods are there only as a
convenience, not to emulate dictionaries.  The TclError
returned ("unknown option...") is clear enough to be handled
in an except clause.

I vote -0 for inclusion of such functionality (`option in
widget`) for LBYL code.
msg67059 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2008-05-19 11:09
Can you tell me why anyone would do `option in widget` ? I don't see the
benefit of making tkinter widgets more "dict-like". Do you have some
good use cases ?
msg67120 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2008-05-20 08:49
I'm closing this; YAGNI.

However, I've added an explicit __contains__ method which raises a nice
error message in r63501.
History
Date User Action Args
2022-04-10 16:05:42adminsetgithub: 37232
2008-05-20 08:49:08georg.brandlsetstatus: open -> closed
nosy: + georg.brandl
resolution: wont fix
messages: + msg67120
2008-05-19 11:53:19benjamin.petersonsettype: enhancement
2008-05-19 11:09:48gpolosetnosy: + gpolo
messages: + msg67059
2002-09-28 04:27:36sbronsoncreate