From: Paul D. F. <pdf...@ku...> - 2005-11-27 00:57:40
|
Just to wrap this up... (even though it is moving off-topic for Jython-dev, but I can add I am impressed I could do it without code changes to Jython. :-) Here is a proof of concept of dynamic code changes while running, based on Kent's suggestion. I and others have done this before even with fancier module reloading and assigning existing instances to a reloaded (so, new) class instance, to get the old instances to use the new class, to get around: http://docs.python.org/lib/built-in-funcs.html "If a module instantiates instances of a class, reloading the module that defines the class does not affect the method definitions of the instances -- they continue to use the old class definition. The same is true for derived classes." but I've never quite seen it this way -- where a previously assigned GUI callback works with the new change, because those references are squirreled away outside the easy reach of module reloaders, and so the GUI continues to callback into the old code (even with the instance referencing the newer reloaded class). Doesn't mean it hasn't been done though, if anyone knows of examples, please let me know. The test consists of two files -- run test.py, it launches two windows, one that can do reloading, one that prints "hello world". Modify the code of the second window in the OnHello method and do a reload. The new OnHello method will be called by the old window when the "hello" button is pressed. You can uncomment the other line, or make your own changes. It's still a little klunky -- it was not obvious to me how to reload a changed module into a new object without brute force removing the old one from sys.modules and then putting it back afterwards. Except for the obvious Swing dependency, I don't see why this would not work under CPython and one of those GUI toolkits (wx, tk, etc.) ====== test.py ============= from javax.swing import JFrame, JButton from java.awt import FlowLayout import sys from hello import HelloFrame class ReloaderFrame(JFrame): def __init__(self): self.contentPane.layout = FlowLayout() button = JButton("Reload", actionPerformed=self.OnReload) self.contentPane.add(button) self.setBounds(50, 100, 100, 100) self.pack() self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) def OnReload(self, event): print "reload" helloModule = sys.modules["hello"] print helloModule print dir(helloModule) print helloModule.HelloFrame print helloModule.HelloFrame.OnHello print helloModule.HelloFrame.OnHello.im_func print helloModule.HelloFrame.OnHello.im_func.func_code # temporarily remove old module and later restore it del sys.modules["hello"] newHelloModule = __import__("hello") sys.modules["hello"] = helloModule print newHelloModule print "helloModule == newHelloModule", helloModule == newHelloModule newFunctionCode = newHelloModule.HelloFrame.OnHello.im_func.func_code print newFunctionCode helloModule.HelloFrame.OnHello.im_func.func_code = newFunctionCode window = ReloaderFrame() window.visible = 1 window = HelloFrame() window.visible = 1 ======================= hello.py ====================== from javax.swing import JFrame, JButton from java.awt import FlowLayout class HelloFrame(JFrame): def __init__(self): self.contentPane.layout = FlowLayout() button = JButton("Hello", actionPerformed=self.OnHello) self.contentPane.add(button) self.setBounds(200, 100, 100, 100) self.pack() self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) def OnHello(self, event): print "hello world" #print "made a change" ========================================================= TO DO: handle updating all the methods in a class, more bells and whistles, changing the code inside the debugger or a popup traceback window, etc.. Don't understand why this has not been done before -- still waiting for the hidden gotchas (beyond obvious module reloading side effects). :-) --Paul Fernhout Paul D. Fernhout wrote: > Thanks again. Now onto a proof of concept towards reloading a Swing GUI > class from a module but modifying what methods of existing graphical > objects do. |