You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/terryjreedy'closed_at=Nonecreated_at=<Date2017-08-26.16:55:38.220>labels= ['expert-IDLE', 'type-feature', '3.7']
title='IDLE: Make GUI test teardown less fragile'updated_at=<Date2017-08-27.20:10:56.780>user='https://github.com/csabella'
When running tests that use an EditorWindow, the following warning message occurs:
warning: callback failed in WindowList <class '_tkinter.TclError'> : invalid command name ".!menu.windows"
This warning comes from call_callbacks in WindowsList in windows.py when the callback is postwindowsmenu() from editor, which is set for the windows menu. The line end = menu.index("end") is the line that fails.
I don't remember ever seeing that message. Do you have code that reliably reproduces the problem?
defpostwindowsmenu(self):
# Only called when Windows menu existsmenu=self.menudict['windows']
end=menu.index("end")
...
windows.add_windows_to_menu(menu)
".!menu.windows" is the tk Windows Menu name, generated by tkinter and saved in menudict. The function claims that it is only called when the menu exists, but the error is that it does not exist, even though it is still in the dict. This is a bug. It must result from a bug either in IDLE or the test teardown code, or maybe both. I would rather fix the bug than shoot the messenger ;-)
Side note: the callback handling strikes me as slightly crazy. Creating a ListedTopLevel calls registry.add, which calls all the callbacks, each of which regenerates the menu.
I saw it on my PR for the tests in outwin (bpo-30617) and I also found a comment from someone else in test_paragraph.py about it.
I can reproduce it with this code:
from idlelib import outwin
from tkinter import Tk, Text
root = Tk()
w = outwin.OutputWindow(None, None, None, root)
w.text = Text(root)
root.mainloop()
I agree that it would be best to fix the root of the problem. I thought maybe with the test, it's the way the OutputWindow is created I tried adding an flist, but that still didn't suppress the warning.
As you gave the code, the two windows just sit there with mainloop running. Replace it with
root.update # likely should add _idletasks()
#w.close()
root.destroy()
and run from IDLE editor and I see the ".!menu.windows" message. Uncomment the close and it goes away.
Root.destroy recursively calls the .destroy methods of its children. Here, ListedTopLevel.destroy is called. It calls TopLevel.destroy and registry.delete. Its menubar child and its dropdown submenu are also destroyed. But LTL.destroy does *not* call the close method of the EditorWindow instance (which is *not* a widget). Without a reference, it cannot.
Registry.delete, which is called for each ListedTopLevel *calls all the callbacks*, which it exactly should not do at shutdown. It does not unregister the associated callback. That is part of editor.close.
In IDLE's normal operation, editor.close must somehow get called. In test setups and teardowns, I am careful to undo things in reverse order of creation. It is, in a sense, a bug, as things now stand, to create an OutputWindow(root) without calling its close method before destroying root.
In configdialog, the callbacks are the Var tracers. The configdialog test teardown removes them all. Closing editorwindows should do the same. This is not to deny that making shutdown less fragile would be a good thing.
I think having separate EditorWindow and EditorFrame classes that *are* widgets would help, as then better auxilliary shutdowns could be either part of or called from the destroy methods that get called when root.destroy is called.
Aside from the ".!menu.windows" message in the idle shell, messages like the following appear in the command window if there is one, with or without the editor.close() call.
invalid command name "96611576font_timer_event"
while executing
"96611576font_timer_event"
("after" script)
"89887864font_timer_event"
("after" script)
invalid command name "89718392timer_event"
while executing
Functions timer_event and font_timer_event are CodeContext methods. The messages don't appear if code_context is not enabled. I don't know how the messages are prevented (normally) when CondContext is enabled. The is no obvious graceful shutdown of the loops. They seem to end when self.text no longer exists so that self.text.after must fail. I already knew that this class needs work ;-).
Thank you for taking the time to research and explain that.
It's funny, but on my code example, I got it to happen every time and you said it didn't happen unless you made the change to use root.update() and root.destroy(). I tried it out again and realized that I was closing the tk window before OutputWindow every time, thus I was getting the warning using root.mainloop(). Of course, if I close OutputWindow first, I don't get the warning. That's running from the command line.
I suppose this issue needs to be split into the real bugs that you mentioned. It seems to be at least 2 or 3 different things to look at (EditorWindow and EditorFrame and CodeContext). I'll delete the current PR for this issue.
I changed the title to express the goal, though I am not sure how to get there yet. One thing is to be more aware of what callbacks and event loops are being set up and possibly not shut down gracefully.
Your code as posted did not reproduce the error *without manual action*. Tests, including the one for bpo-30617, has better run without user intervention. Once I made the modification to get the error, or not, just by running it, I was pretty sure of the fix for the test.
changed the title [-]IDLE: Fix WindowList invalid command name error when running tests[/-][+]IDLE: Make GUI test teardown less fragile[/+]on Aug 27, 2017
Activity
csabella commentedon Aug 26, 2017
When running tests that use an EditorWindow, the following warning message occurs:
warning: callback failed in WindowList <class '_tkinter.TclError'> : invalid command name ".!menu.windows"
This warning comes from
call_callbacksin WindowsList in windows.py when the callback ispostwindowsmenu()from editor, which is set for thewindowsmenu. The lineend = menu.index("end")is the line that fails.terryjreedy commentedon Aug 26, 2017
I don't remember ever seeing that message. Do you have code that reliably reproduces the problem?
".!menu.windows" is the tk Windows Menu name, generated by tkinter and saved in menudict. The function claims that it is only called when the menu exists, but the error is that it does not exist, even though it is still in the dict. This is a bug. It must result from a bug either in IDLE or the test teardown code, or maybe both. I would rather fix the bug than shoot the messenger ;-)
Side note: the callback handling strikes me as slightly crazy. Creating a ListedTopLevel calls registry.add, which calls all the callbacks, each of which regenerates the menu.
csabella commentedon Aug 26, 2017
I saw it on my PR for the tests in outwin (bpo-30617) and I also found a comment from someone else in test_paragraph.py about it.
I can reproduce it with this code:
from idlelib import outwin
from tkinter import Tk, Text
root = Tk()
w = outwin.OutputWindow(None, None, None, root)
w.text = Text(root)
root.mainloop()
I agree that it would be best to fix the root of the problem. I thought maybe with the test, it's the way the OutputWindow is created I tried adding an flist, but that still didn't suppress the warning.
terryjreedy commentedon Aug 27, 2017
As you gave the code, the two windows just sit there with mainloop running. Replace it with
root.update # likely should add _idletasks()
#w.close()
root.destroy()
and run from IDLE editor and I see the ".!menu.windows" message. Uncomment the close and it goes away.
Root.destroy recursively calls the .destroy methods of its children. Here, ListedTopLevel.destroy is called. It calls TopLevel.destroy and registry.delete. Its menubar child and its dropdown submenu are also destroyed. But LTL.destroy does *not* call the close method of the EditorWindow instance (which is *not* a widget). Without a reference, it cannot.
Registry.delete, which is called for each ListedTopLevel *calls all the callbacks*, which it exactly should not do at shutdown. It does not unregister the associated callback. That is part of editor.close.
In IDLE's normal operation, editor.close must somehow get called. In test setups and teardowns, I am careful to undo things in reverse order of creation. It is, in a sense, a bug, as things now stand, to create an OutputWindow(root) without calling its close method before destroying root.
In configdialog, the callbacks are the Var tracers. The configdialog test teardown removes them all. Closing editorwindows should do the same. This is not to deny that making shutdown less fragile would be a good thing.
I think having separate EditorWindow and EditorFrame classes that *are* widgets would help, as then better auxilliary shutdowns could be either part of or called from the destroy methods that get called when root.destroy is called.
Aside from the ".!menu.windows" message in the idle shell, messages like the following appear in the command window if there is one, with or without the editor.close() call.
invalid command name "96611576font_timer_event"
while executing
"96611576font_timer_event"
("after" script)
"89887864font_timer_event"
("after" script)
invalid command name "89718392timer_event"
while executing
Functions timer_event and font_timer_event are CodeContext methods. The messages don't appear if code_context is not enabled. I don't know how the messages are prevented (normally) when CondContext is enabled. The is no obvious graceful shutdown of the loops. They seem to end when self.text no longer exists so that self.text.after must fail. I already knew that this class needs work ;-).
csabella commentedon Aug 27, 2017
Thank you for taking the time to research and explain that.
It's funny, but on my code example, I got it to happen every time and you said it didn't happen unless you made the change to use root.update() and root.destroy(). I tried it out again and realized that I was closing the tk window before OutputWindow every time, thus I was getting the warning using root.mainloop(). Of course, if I close OutputWindow first, I don't get the warning. That's running from the command line.
I suppose this issue needs to be split into the real bugs that you mentioned. It seems to be at least 2 or 3 different things to look at (EditorWindow and EditorFrame and CodeContext). I'll delete the current PR for this issue.
Thanks!
terryjreedy commentedon Aug 27, 2017
I closed the patch; you can delete the branch.
I changed the title to express the goal, though I am not sure how to get there yet. One thing is to be more aware of what callbacks and event loops are being set up and possibly not shut down gracefully.
Your code as posted did not reproduce the error *without manual action*. Tests, including the one for bpo-30617, has better run without user intervention. Once I made the modification to get the error, or not, just by running it, I was pretty sure of the fix for the test.
[-]IDLE: Fix WindowList invalid command name error when running tests[/-][+]IDLE: Make GUI test teardown less fragile[/+]