[issue15133] tkinter.BooleanVar.get() behavior and docstring disagree
klappnase added the comment: The behavior of Tkinter when handling boolean values appears to be a bit erratic at times, not only BooleanVar.get() returns 0/1 instead of True/False (e.g. see the thread at tkinter-discuss: http://mail.python.org/pipermail/tkinter-discuss/2012-June/003176.html ). This is apparently because tk itself uses the strings '0' and '1' as boolean values, so behind the scenes Tkinter has to convert any bool into a string when setting a value and the string back into a bool when retrieving it, and it seems like most of the Tkinter code (and docstrings) was written in the good ol' days when Python used 0 / 1 itself. Now when it comes to change Tkinter's behavior I'd tend to be careful. For example BooleanVar.get() could easily be changed to always return True/False. But imho this change would only make sense if you add strict input value checking for set() either, otherwise we just change one incoherency with another. But this would mean that we might end up breaking a lot of working code, for what seems to me a primarily aesthetic reason. And of course, I don't see much use in isolated changes of the behavior of one function here and another method there. I feel that if the behavior of Tkinter concerning bool values was to be changed, there should at least be a thorough change of *any* Tkinter method that gets / sets boolean values so we at least end up with an overall coherent solution. But again, this looks like quite a lot of work, will break running code and add no significant benefit besides a cosmetic improvement. So my vote goes to accepting that 0 and 1 are ok boolean values in Tkinter and changing no more than misleading docstrings, as in this example of BooleanVar.get(): def get(self): """Return the value of the variable as 1 (True) or 0 (False).""" return self._tk.getboolean(self._tk.globalgetvar(self._name)) -- nosy: +klappnase ___ Python tracker <http://bugs.python.org/issue15133> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15133] tkinter.BooleanVar.get() behavior and docstring disagree
klappnase added the comment: I agree that get() should better return a boolean in any case, however the bug then is not one of BooleanVar but rather one of tk.getboolean(). I did some experimenting with get() and it seems that there are three possibilities: getboolean() returns True/False as it should when the variable value was previously set() to anything Tcl accepts as boolean value (like 'yes'/'no', '0'/'1', 'on'/'off', 'true'/'false'). If something which is not a proper Tcl-bool was passed to set() before, getboolean will produce a TclError or TypeError. If set() got 0/1 (as integers) or True/False before, getboolean() will return 0/1 and this appears to me to be the only bug here. But this is not at all a sole BooleanVar bug, e.g.: >>> root=Tk() >>> root.tk_strictMotif() 0 >>> root.tk_strictMotif(1) 1 You will find this everywhere in Tkinter where getboolean() is used, so I think that rather this should be fixed in _tkinter.c than applying a workaround to BooleanVar.get() and leaving all other uses of getboolean() as they are; even worse, if BooleanVar.set() was changed to accept only True/False and getboolean() left as it is, you could not pass the return value of getboolean() any longer to BooleanVar.get() which would be really bad. As far as set() is concerned, it should at least allow everything that Tcl accepts as boolean, according to http://wiki.tcl.tk/16235 these are at least the above mentioned 'yes'/'no', '0'/'1', 'on'/'off', 'true'/'false' (btw. all of these seem to be ok even case insensitive on the tcl side) plus of course 0/1 and True/False. Otherwise it might break existing code. Terry: "Since the purpose of Variables is to synchronize values between user code and tk, TypeVar().set(x).get() should be x when has the proper type. That is now true for everything but bool/Boolean." But when the input type is not proper you can do e.g.: >>> d = DoubleVar() >>> d.set('1.1') >>> d.get() 1.1 >>> i = IntVar() >>> i.set(True) >>> i.get() 1 >>> I think the Variable classes can also be considered convenience objects that save the application programmer a lot of headaches when they have to convert Python objects into Tcl which usually expects strings, so I think there is nothing wrong with set() accepting "improper" values. -- ___ Python tracker <http://bugs.python.org/issue15133> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue15133] tkinter.BooleanVar.get() behavior and docstring disagree
klappnase added the comment: "...you could not pass the return value of getboolean() any longer to BooleanVar.get() which would be really bad." Ooops, typo, should be BooleanVar.set() of course. -- ___ Python tracker <http://bugs.python.org/issue15133> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
klappnase added the comment: > What is your real name? Michael Lange > What should I add in the Misc/ACKS file? Hmm, personally I'd prefer the nick, but it seems to be common practice to use the real name; I think I'll leave it to you ;) -- ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
klappnase added the comment: > Are 'unloaded but available' themes really available to use? Yes. > Does Style.theme_use(available_name) work? Yes. > If so, it seems to me that available_name should > be reported by theme_names. I agree, one should think so. I am not 100% certain about that, but to me it seems that on the tcl side ttk:themes is newer and thus preferable to theme names which maybe is only still there for backwards compatibility. Since as a Tkinter user I like Tkinter methods to behave like their Tcl/Tk counterparts (which, if nothing else, helps a lot in reading and understanding tcl code/documentation (and possibly "translating" tcl code into Python)) I had rather kept theme_names() intact to avoid confusion. Maybe there could simply a line like "Deprecated since Python-xy, use themes() instead." be added to theme_names' doc string ? -- ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue1525806] Tkdnd mouse cursor handling patch
klappnase added the comment: Maybe this depends on whether the dragged item is "clickable" like listbox items and buttons or not , like the Labels in the Tkdnd demo. Ok, I wrote a second patch that solves this by adding another option to dnd_start(); if this option is set to True (the default) the user gets the classic behavior, if set to False the cursor changes when the motion starts, as in the initial patch. I couldn't figure out a good name for this option, so I called it "swapcursoronclick", at least the name says what it is for ^_^ -- Added file: http://bugs.python.org/file13750/Tkdnd.diff ___ Python tracker <http://bugs.python.org/issue1525806> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing form ttk.py
New submission from klappnase: When trying to load third-party themes ttk.Style.theme_names() fails to list available themes. For example if the themes from the tile-themes project are installed one can do: >>> from tkinter import * >>> from tkinter import ttk >>> root=Tk() >>> s=ttk.Style() >>> s.theme_names() ('clam', 'alt', 'default', 'classic') >>> root.tk.call('ttk::themes') ('classic', 'default', 'clam', 'alt') >>> root.tk.call('package', 'require', 'tile-themes') '0.6' >>> s.theme_names() ('clam', 'alt', 'default', 'classic') >>> root.tk.call('ttk::themes') ('keramik', 'plastik', 'clam', 'winxpblue', 'alt', 'Aquativo', 'classic', 'default', 'keramik_alt') >>> This has been discussed in more detail at tkinter-discuss: http://code.activestate.com/lists/python-tkinter-discuss/3373/ As ttk::themes is described as being part of the Public API inside ttk.tcl and is also documented in the tcl wiki at http://wiki.tcl.tk/14796 resp. http://wiki.tcl.tk/23676 it appears safe to add it to ttk.py. Considering this I prepared a patch (against b10a9d4f08eb) that adds the following method to ttk.Style(): def themes(self, pattern=None): '''Returns a list of theme names available. It can be passed an argument which is used as an lsearch glob pattern while looking for the theme names.''' return self.tk.splitlist(self.tk.call('ttk::themes', pattern)) -- components: Tkinter files: patch_ttk.diff keywords: patch messages: 183954 nosy: klappnase priority: normal severity: normal status: open title: ttk::themes missing form ttk.py type: enhancement Added file: http://bugs.python.org/file29377/patch_ttk.diff ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
Changes by klappnase : -- title: ttk::themes missing form ttk.py -> ttk::themes missing from ttk.py ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
klappnase added the comment: I am not familiar with python's test unit, but I tried my best. As far as I see there are three possibilities to invoke the function: * without pattern -> return tuple with all themes * with pattern that matches one or more themes * with pattern that matches no themes -> return empty tuple So I tried to add a method to test_style.StyleTest() : def test_themes(self): installed_themes = self.style.themes() some_themes = self.style.themes('*e*') no_themes = self.style.themes('foobarbaz') self.assertTrue(isinstance(installed_themes, tuple)) self.assertTrue(isinstance(some_themes, tuple)) self.assertTrue(isinstance(no_themes, tuple)) Oddly enough this fails on my own system (debian squeeze, tk-8.5.8, python-3.1.3 / -2.6.6): $ python3 test_style.py test_configure (__main__.StyleTest) ... ok test_layout (__main__.StyleTest) ... ok test_lookup (__main__.StyleTest) ... ok test_map (__main__.StyleTest) ... ok test_theme_use (__main__.StyleTest) ... ok test_themes (__main__.StyleTest) ... ERROR == ERROR: test_themes (__main__.StyleTest) -- Traceback (most recent call last): File "test_style.py", line 97, in test_themes no_themes = self.style.themes('foobarbaz') File "/usr/lib/python3.1/tkinter/ttk.py", line 536, in themes return self.tk.splitlist(self.tk.call('ttk::themes', pattern)) TypeError: Can't convert '_tkinter.Tcl_Obj' object to str implicitly -- Ran 6 tests in 0.086s FAILED (errors=1) Traceback (most recent call last): File "test_style.py", line 108, in run_unittest(*tests_gui) File "/usr/lib/python3.1/test/support.py", line 955, in run_unittest _run_suite(suite) File "/usr/lib/python3.1/test/support.py", line 938, in _run_suite raise TestFailed(err) test.support.TestFailed: Traceback (most recent call last): File "test_style.py", line 97, in test_themes no_themes = self.style.themes('foobarbaz') File "/usr/lib/python3.1/tkinter/ttk.py", line 536, in themes return self.tk.splitlist(self.tk.call('ttk::themes', pattern)) TypeError: Can't convert '_tkinter.Tcl_Obj' object to str implicitly The same error occurs with python-2.6.6 (same tk). Apparently this is because: $ python3 Python 3.1.3 (r313:86834, Nov 28 2010, 11:28:10) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from tkinter import * >>> from tkinter import ttk >>> r=Tk() >>> s=ttk.Style() >>> x = s.themes('foo') Traceback (most recent call last): File "", line 1, in File "/usr/lib/python3.1/tkinter/ttk.py", line 536, in themes return self.tk.splitlist(self.tk.call('ttk::themes', pattern)) TypeError: Can't convert '_tkinter.Tcl_Obj' object to str implicitly >>> x=r.tk.call('ttk::themes', 'foo') >>> x >>> str(x) '' >>> Called from wish the same call returns an empty string as expected: $ wish % ttk::themes classic default clam alt % ttk::themes *e* default % ttk::themes foobarbaz % In python2.6, when setting Tkinter.wantobjects to 0, themes('foo') returns an empty tuple as expected. So I guess this is due to a bug in debian's python/tkinter install. Can anyone confirm this? -- ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
klappnase added the comment: Update: I just tried Python-3.3.0 on WinXP, the same error, so it is obviously _not_ a bug specific to the debian python install. -- ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue17397] ttk::themes missing from ttk.py
klappnase added the comment: Yes, I happen to encounter these TclObjects occasionally, e.g. (not tested with the latest python): $ python3 Python 3.1.3 (r313:86834, Nov 28 2010, 11:28:10) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from tkinter import * >>> from tkinter import ttk >>> r=Tk() >>> p=ttk.Progressbar(r) >>> p.cget('mode') >>> print(p.cget('mode')) determinate >>> p.cget('mode') == 'determinate' False >>> str(p.cget('mode')) == 'determinate' True >>> In Python2 the easiest way to work around this imho is to set wantobjects to 0, however this does not seem to work in Python3 anymore, not sure if this is for some reason intentional or deserves another bug report: $ python3 Python 3.1.3 (r313:86834, Nov 28 2010, 11:28:10) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import tkinter >>> tkinter.wantobjects = 0 >>> from tkinter import ttk >>> r=tkinter.Tk() >>> p=ttk.Progressbar(r) >>> p.cget('mode') '' >>> To be honest, since these TclObjects never seem to work reliably I had preferred it a lot if they would have been turned off by default. -- ___ Python tracker <http://bugs.python.org/issue17397> ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Funny thing, just today I came across the same issue. So far I came up with an a little bit refined version of the OP's suggestions. Until now I have tested this with Python-2.7.9 and tk-8.6.0 on debian Jessie, I think the same code should work for Python-3 , too. The busy_current() function here always reports only the root window (the same when called from within wish, apparently a bug in this early version of Tk-8.6) so I was not able to figure out how to use and test the "pattern" option. def busy(self, **kw): '''Shortcut for the busy_hold() command.''' self.tk.call(('tk', 'busy', self._w) + self._options(kw)) def busy_cget(self, option): '''Queries the busy command configuration options for this window. The window must have been previously made busy by the busy_hold() command. Returns the present value of the specified option. Option may have any of the values accepted by busy_hold().''' return(self.tk.call('tk', 'busy', 'cget', self._w, '-'+option)) def busy_configure(self, cnf=None, **kw): '''Queries or modifies the tk busy command configuration options. The window must have been previously made busy by busy_hold(). Option may have any of the values accepted by busy_hold(). Please note that the option database is referenced by the window. For example, if a Frame widget is to be made busy, the busy cursor can be specified for it by : w.option_add("*Frame.BusyCursor", "gumby")''' if kw: cnf = _cnfmerge((cnf, kw)) elif cnf: cnf = _cnfmerge(cnf) if cnf is None: return(self._getconfigure( 'tk', 'busy', 'configure', self._w)) if type(cnf) is StringType: return(self._getconfigure1( 'tk', 'busy', 'configure', self._w, '-'+cnf)) self.tk.call(( 'tk', 'busy', 'configure', self._w) + self._options(cnf)) busy_config = busy_configure def busy_current(self, pattern=None): '''Returns the widget objects of all widgets that are currently busy. If a pattern is given, only the path names of busy widgets matching PATTERN are returned. ''' return([self._nametowidget(x) for x in self.tk.splitlist(self.tk.call( 'tk', 'busy', 'current', self._w, pattern))]) def busy_forget(self): '''Releases resources allocated by the busy() command for this window, including the transparent window. User events will again be received by the window. Resources are also released when the window is destroyed. The window must have been specified in the busy_hold() operation, otherwise an exception is raised.''' self.tk.call('tk', 'busy', 'forget', self._w) def busy_hold(self, **kw): '''Makes this window (and its descendants in the Tk window hierarchy) appear busy. A transparent window is put in front of the specified window. This transparent window is mapped the next time idle tasks are processed, and the specified window and its descendants will be blocked from user interactions. Normally update() should be called immediately afterward to insure that the hold operation is in effect before the application starts its processing. The following configuration options are valid: -cursor cursorName Specifies the cursor to be displayed when the widget is made busy. CursorName can be in any form accepted by Tk_GetCursor. The default cursor is "wait" on Windows and "watch" on other platforms.''' self.tk.call(( 'tk', 'busy', 'hold', self._w) + self._options(kw)) def busy_status(self): '''Returns the busy status of this window. If the window presently can not receive user interactions, True is returned, otherwise False.''' return((self.tk.getboolean(self.tk.call( 'tk', 'busy', 'status', self._w)) and True) or False) -- nosy: +klappnase ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Oops, just made a quick test with Python3, and found that I had missed that types.StringType is no longer present. So to be compatible with Python3 the busy_configure() func ought to look like: def busy_configure(self, cnf=None, **kw): if kw: cnf = _cnfmerge((cnf, kw)) elif cnf: cnf = _cnfmerge(cnf) if cnf is None: return(self._getconfigure( 'tk', 'busy', 'configure', self._w)) if isinstance(cnf, str): return(self._getconfigure1( 'tk', 'busy', 'configure', self._w, '-'+cnf)) self.tk.call(( 'tk', 'busy', 'configure', self._w) + self._options(cnf)) -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Ok, I investigated this a little further. First I noticed another bug with the code from my first post, the "self._w" must be omitted from the call to busy_current(), so the func should look like: def busy_current(self, pattern=None): return([self._nametowidget(x) for x in self.tk.splitlist(self.tk.call( 'tk', 'busy', 'current', pattern))]) I did then some more testing, the code now seems to work flawlessly both with Python-3.5.2 on windows 10 and with Python 2.7 on debian Jessie. So I finally prepared a patch (against the __init__.py file from the 3.5.2 windows installer). Following Miguel's suggestion I also added aliases prefixed with tk_ to the various busy_... methods. Since I am not familiar with Python's "official" test mechanisms, for now I wrote a simple script that does a number of calls to the tk_busy_... functions to test if everything works as expected: try: import Tkinter except: import tkinter as Tkinter #Tkinter.wantobjects = False root = Tkinter.Tk() f = Tkinter.Frame(root, name='f') f.pack(fill='both', expand=1) b=Tkinter.Button(f, name='b', text='hi', command=root.bell) b.pack(padx=100, pady=100) top = Tkinter.Toplevel(root, name='top') def test1(): root.tk_busy() def test2(): root.tk_busy_forget() def test3(): root.tk_busy_hold(cursor='gumby') def test4(): root.tk_busy_forget() def test5(): root.tk_busy_hold() top.tk_busy(cursor='gumby') print(root.tk_busy_current()) print(root.tk_busy_current(pattern='*t*')) def test6(): print(root.tk_busy_current()) def test7(): root.tk_busy_configure(cursor='gumby') def test8(): print(root.tk_busy_configure()) print(root.tk_busy_configure('cursor')) print(root.tk_busy_cget('cursor')) def test9(): print(root.tk_busy_status()) def test10(): root.tk_busy_forget() print(root.tk_busy_status()) print(root.tk_busy_current()) delay = 0 for test in (test1, test2, test3, test4, test5, test6, test7, test8, test9, test10): delay += 1000 root.after(delay, test) root.mainloop() -- keywords: +patch Added file: http://bugs.python.org/file45190/tk_busy.diff ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: @Miguel About tk_busy_configure(): I strongly suggest that my version of tk_busy_configure() is better, since it behaves exactly like the usual configure() methods in Tkinter (which includes e.g. Canvas.itemconfigure() or Text.tag_configure()), i.e. you can not only change the values of the configuration options, but also query available options and their default values. I think *this* follows the usual Tkinter conventions. As you pointed out in your last post, I could not use _configure() directly for this, but had to "duplicate" the code with a slight modification, because of the order of arguments for tk_busy_configure(). The reason that this construct is not used for pack_configure() is simply that widget.pack_configure() does not return anything if called without arguments (in fact it appears to be the very same as widget.pack()). About busy_status(): the construct I use here is to work around the broken _getboolean() which does not always return True or False, but often returns None instead of False (if wantobjects==True). Therefore I used (unlike most Tkinter methods) tkapp.getboolean() directly, however quite a while ago I noticed that this was broken, too, and sometimes returned 0 or 1 instead of True or False. However I admit that I did not test right now if this is still the case, in fact I just copy'n'pasted it from code I already use and that works perfectly well (BTW, I suggested the same method to fix these issue with _getboolean() here some time ago, and of course I agree that it would be preferrable to fix _getboolean() and possibly tkapp.getboolean() in the first place). @Serhiy Thanks for the link, I did not find the source tree on the new python web site (I admit I did not look too hard :) . I now added a patch against the default branch'es __init__.py . Doc strings are (still :) included. I also changed the function names according to Miguel's suggestion. I'll see if I find the time to add a proper test class one of these days (you guys make it really hard for outsiders to help out ;) -- Added file: http://bugs.python.org/file45193/tk_busy.diff ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: As far as I can see, most internal Tkinter methods use _getboolean(), which currently looks like: def _getboolean(self, string): """Internal function.""" if string: return self.tk.getboolean(string) I am not 100% sure about this, but I figure that when this was written it was intentional that if "string" is an empty string, it should return None instead of (back then) 0 or 1. Today this would probably translate into something like: def _getboolean(self, value): if not value in ('', None): return bool(self.tk.getboolean(value)) -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Hi Miguel, about _configure() : the code you suggest: def _configure(self, cmd, cnf, kw): """Internal function.""" if kw: cnf = _cnfmerge((cnf, kw)) elif cnf: cnf = _cnfmerge(cnf) if cnf is None: return self._getconfigure(cmd) if isinstance(cnf, str): return self._getconfigure1(cmd + ('-'+cnf,)) self.tk.call(cmd + self._options(cnf)) will break all other methods that use configure() and friends. A possible way to work around this might be: def _configure(self, cmd, cnf, kw): """Internal function.""" if kw: cnf = _cnfmerge((cnf, kw)) elif cnf: cnf = _cnfmerge(cnf) if not self._w in cmd: cmd = _flatten((self._w, cmd)) if cnf is None: return self._getconfigure(cmd) if isinstance(cnf, str): return self._getconfigure1(cmd + ('-'+cnf,)) self.tk.call(cmd + self._options(cnf)) Not sure if this is smart, though, it might require some thorough testing. About getboolean() : it seems like tkapp.getboolean() returns 1 or 0 when it is passed an integer value, at least this is still true here for Python-3.4.2: $ python3 Python 3.4.2 (default, Oct 8 2014, 10:45:20) [GCC 4.9.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from tkinter import * >>> r=Tk() >>> getboolean(1) 1 >>> getboolean('1') True >>> getboolean('yes') True >>> getboolean(True) True >>> Probably the best thing to do would be to fix this in the C code. The next best thing I think is to change tkinter.getboolean(), tkinter.Misc.getboolean() and tkinter.Misc._getboolean(). This however leaves a number of Tkinter methods like e.g. Text.compare() which directly use self.tk.getboolean() unresolved. -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Your changed _configure() will also break Canvas/Listbox.itemconfigure(), Menu.entryconfigure() and a number of other methods, Tix is also affected. It will also break third party extensions that use _configure(), like pybwidget. As another python motto says "Special cases aren't special enough to break the rules." :) I believe that breaking existing code is not justified by the "special case" of the tk_busy_configure() syntax, resp. the desire to avoid 10 extra lines of code. The change to _configure() I suggested otoh leaves all the existing configure()-like methods intact, and it seems at least very unlikely that some third party module uses a configure()-like method that adds the window path name to the cmd-tuple (which indeed would break my _configure() example. However, following the "explicit is better than implicit" motto, I believe the best idea, if _configure() should be changed at all, is to add a new option to let the programmer decide if the window path should be added to the cmd tuple, which defaults to a value that keeps the old behavior intact, as in this example: def _configure(self, cmd, cnf, kw, usewinpath=True): """Internal function.""" if kw: cnf = _cnfmerge((cnf, kw)) elif cnf: cnf = _cnfmerge(cnf) if usewinpath: cmd = _flatten((self._w, cmd)) else: cmd = _flatten(cmd) if cnf is None: return self._getconfigure(cmd) if isinstance(cnf, str): return self._getconfigure1(cmd + ('-'+cnf,)) self.tk.call(cmd + self._options(cnf)) Then busy_configure might look like: def busy_configure(self, cnf=None, **kw): return self._configure(('tk', 'busy', 'configure', self._w), cnf, kw, usewinpath=False) -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: "Also it's more efficient to use this than the function _flaten() in that situation: if not self._w in cmd: cmd = (self._w,) + cmd " The construct with _flatten() was not my invention, it's probably something to discuss with Guido ;) The advantage of _flatten() may be, that it will also handle nested tuples properly, though I don't know if there is a real-life situation whee nested tuples might show up there. Anyway, thinking about optimisations on that level seems somewhat pointless to me, no one will probably iterate over configure() calls, and if yes, the bottleneck is clearly the self.tk.call() part. -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: "This is my point of view: These functions are easy to change: itemconfigure(), entryconfigure(), image_configure(), tag_configure() and window_configure() It's only to add self._w in the proper place. Only one line per method" At least Tix would have to be changed, too. "Other third party extensions should not rely on _configure() because it's an internal method (it starts with underscore). We have rights to change the semantics of this internal method in any moment without notification." But why insist on your rights, if there is no actual need to do this? The function I posted in my previous message for example serves the same purpose without having to change any other function call and without breaking any third-party code that possibly uses _configure(). You sure have the right to do this, but I feel it is at least somewhat unfriendly if it is done without necessity. Besides, one thing I missed in my last post: "Also it's more efficient to use this than the function _flaten() in that situation: if not self._w in cmd: cmd = (self._w,) + cmd " If you want to discard the use of _flatten() you would also have to change Misc.configure() . -- components: +Library (Lib), Tkinter -Installation ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: And another thing: "There is no test that shows that self.tk.getboolean is buggy." Well... $ python3 Python 3.4.2 (default, Oct 8 2014, 10:45:20) [GCC 4.9.1] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import tkinter >>> root=tkinter.Tk() >>> root.tk.getboolean(root.tk_strictMotif()) 0 >>> -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: The bug is that tk_strictMotif (which uses self.tk.getboolean() itself) returns 0 instead of False. I used the "nested" command to point out, that self.tk.getboolean() is broken when used with wantobjects=True, because it does *not* return proper boolean values , i.e. True or False. It is probably the reduction to handling strings only that you mentioned that causes this wrong behavior, because with wantobjects=True self.tk.call() will convert the "0" tk_strictMotif returns into 0 which is not handled properly. With wantobjects=False, it will retunr True/False as expected. Its behavior is not consistent, *that* is the bug. But to be honest, personally I don't give a dime if these calls return True/False or 1/0, I just wanted to make clear why I explicitely converted the output of self.tk.getboolean() in my tk_busy_status function. I believed that proper boolean values (True/False) were the desired thing. I personally agree with you about the busy_status function, my construct is not necessary, if someone does not like it to return 0/1 , tkapp.getboolean() should be fixed instead. And again I admit that I don't remember why I used that construct instead of just passing the result to bool(). I am quite sure I had a reason for this when I started to use this construct first some years ago, but back then tkapp.getboolean() behaved differently (and worse), some of which was apparently fixed in the meantime. And one more time about _configure(): "I like elegancy..." So do I, but can't expanding the functionality of a method by adding a new option be considered a more elegant solution than entirely changing its behavior with the effect of having to change a number of other things, too? (though I admit that the name for this option I picked first should seriously be reconsidered if it's supposed to be called "elegant", I confess that I am notoriously dumb in inventing names :) -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: At least with python 3.4 here wantobjects still is valid, and personally I really hope that it remains this way, because I use to set wantobjects=False in my own code to avoid having to deal with errors because of some method or other unexpectedly returning TclObjects instead of Python objects (which has been happening here occasionally ever since they were invented). I am practically illiterate with C, so I cannot tell what this code does, but at least I believe I see clearly here that it appears to be still used: static TkappObject * Tkapp_New(const char *screenName, const char *className, int interactive, int wantobjects, int wantTk, int sync, const char *use) { TkappObject *v; char *argv0; v = PyObject_New(TkappObject, (PyTypeObject *) Tkapp_Type); if (v == NULL) return NULL; Py_INCREF(Tkapp_Type); v->interp = Tcl_CreateInterp(); v->wantobjects = wantobjects; v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded", TCL_GLOBAL_ONLY) != NULL; v->thread_id = Tcl_GetCurrentThread(); v->dispatching = 0; (...) static PyObject* Tkapp_CallResult(TkappObject *self) { PyObject *res = NULL; Tcl_Obj *value = Tcl_GetObjResult(self->interp); if(self->wantobjects) { /* Not sure whether the IncrRef is necessary, but something may overwrite the interpreter result while we are converting it. */ Tcl_IncrRefCount(value); res = FromObj((PyObject*)self, value); Tcl_DecrRefCount(value); } else { res = unicodeFromTclObj(value); } return res; } -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Hi Serhiy, thanks for the feedback. "+def tk_busy(self, **kw): Shouldn't it be just an alias to tk_busy_hold?" Not sure, I figured since it is a separate command in tk I would make it a separate command in Python, too. "+def tk_busy_hold(self, **kw): Since the only supported option is cursor, just declare it. def tk_busy_hold(self, cursor=None): " I thought so at first, too, but is this really wise, since if future versions of tk add other options another patch would be required? -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Ok, I hope I applied all the required changes now. The tests seemed to me to belong to test_misc, so I just added another function to the MiscTest class, I hope that is ok. The test runs well here, so I hope I did everything correctly. Thanks for your patience! -- Added file: http://bugs.python.org/file45230/tk_busy_3.diff ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: Oops, I guess I violated PEP257 again, sorry, corrected version #4 attached. -- Added file: http://bugs.python.org/file45231/tk_busy_4.diff ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28498] tk busy command
klappnase added the comment: This is something entirely different, since the commands you list here in tk do not accept keyword arguments at all. -- ___ Python tracker <http://bugs.python.org/issue28498> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com