From 7cca28ffa2efff47d4c53080f49c5b5c8eebbc19 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 10 Jul 2014 01:16:49 -0400 Subject: [PATCH] Issue #21940: add docstrings to idlelib.WidgetRedirector. --- Lib/idlelib/WidgetRedirector.py | 78 +++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/Lib/idlelib/WidgetRedirector.py b/Lib/idlelib/WidgetRedirector.py index 5ee42989003..e7377d5b174 100644 --- a/Lib/idlelib/WidgetRedirector.py +++ b/Lib/idlelib/WidgetRedirector.py @@ -1,7 +1,6 @@ -from tkinter import * +from tkinter import TclError class WidgetRedirector: - """Support for redirecting arbitrary widget subcommands. Some Tk operations don't normally pass through Tkinter. For example, if a @@ -18,12 +17,22 @@ class WidgetRedirector: this command and provide a facility ('register') to intercept the widget operation. - In IDLE, the function being registered provides access to the top of a - Percolator chain. At the bottom of the chain is a call to the original - Tk widget operation. - + In IDLE, WidgetRedirector is used in Percolator to intercept Text + commands. The function being registered provides access to the top + of a Percolator chain. At the bottom of the chain is a call to the + original Tk widget operation. """ def __init__(self, widget): + '''Initialize attributes and setup redirection. + + _operations: dict mapping operation name to new function. + widget: the widget whose tcl command is to be intercepted. + tk: widget.tk, a convenience attribute, probably not needed. + orig: new name of the original tcl command. + + Since renaming to orig fails with TclError when orig already + exists, only one WidgetDirector can exist for a given widget. + ''' self._operations = {} self.widget = widget # widget instance self.tk = tk = widget.tk # widget's root @@ -40,22 +49,34 @@ class WidgetRedirector: self.widget._w) def close(self): + "Unregister operations and revert redirection created by .__init__." for operation in list(self._operations): self.unregister(operation) - widget = self.widget; del self.widget - orig = self.orig; del self.orig + widget = self.widget tk = widget.tk w = widget._w + # Restore the original widget Tcl command. tk.deletecommand(w) - # restore the original widget Tcl command: - tk.call("rename", orig, w) + tk.call("rename", self.orig, w) + del self.widget, self.tk # Should not be needed + # if instance is deleted after close, as in Percolator. def register(self, operation, function): + '''Return OriginalCommand(operation) after registering function. + + Registration adds an instance function attribute that masks the + class instance method attribute. If a second function is + registered for the same operation, the first function is replaced. + ''' self._operations[operation] = function setattr(self.widget, operation, function) return OriginalCommand(self, operation) def unregister(self, operation): + '''Return the function for the operation, or None. + + Deleting the instance attribute unmasks the class attribute. + ''' if operation in self._operations: function = self._operations[operation] del self._operations[operation] @@ -88,14 +109,29 @@ class WidgetRedirector: class OriginalCommand: + '''Callable for original tk command that has been redirected. + + Returned by .register; can be used in the function registered. + redir = WidgetRedirector(text) + def my_insert(*args): + print("insert", args) + original_insert(*args) + original_insert = redir.register("insert", my_insert) + ''' def __init__(self, redir, operation): + '''Create .tk_call and .orig_and_operation for .__call__ method. + + .redir and .operation store the input args for __repr__. + .tk and .orig copy attributes of .redir (probably not needed). + ''' self.redir = redir self.operation = operation - self.tk = redir.tk - self.orig = redir.orig - self.tk_call = self.tk.call - self.orig_and_operation = (self.orig, self.operation) + self.tk = redir.tk # redundant with self.redir + self.orig = redir.orig # redundant with self.redir + # These two could be deleted after checking recipient code. + self.tk_call = redir.tk.call + self.orig_and_operation = (redir.orig, operation) def __repr__(self): return "OriginalCommand(%r, %r)" % (self.redir, self.operation) @@ -104,7 +140,10 @@ class OriginalCommand: return self.tk_call(self.orig_and_operation + args) -def _widget_redirector(parent): +def _widget_redirector(parent): # htest # + from tkinter import Tk, Text + import re + root = Tk() root.title("Test WidgetRedirector") width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) @@ -113,13 +152,16 @@ def _widget_redirector(parent): text.pack() text.focus_set() redir = WidgetRedirector(text) - global previous_tcl_fcn def my_insert(*args): print("insert", args) - previous_tcl_fcn(*args) - previous_tcl_fcn = redir.register("insert", my_insert) + original_insert(*args) + original_insert = redir.register("insert", my_insert) root.mainloop() if __name__ == "__main__": + import unittest +## unittest.main('idlelib.idle_test.test_widgetredir', +## verbosity=2, exit=False) + from idlelib.idle_test.htest import run run(_widget_redirector)