[Python-checkins] cpython (3.4): Issue #21940: add docstrings to idlelib.WidgetRedirector.

terry.reedy python-checkins at python.org
Thu Jul 10 07:17:53 CEST 2014


http://hg.python.org/cpython/rev/220d5fdbe22e
changeset:   91623:220d5fdbe22e
branch:      3.4
parent:      91620:5be778fec115
user:        Terry Jan Reedy <tjreedy at udel.edu>
date:        Thu Jul 10 01:16:49 2014 -0400
summary:
  Issue #21940: add docstrings to idlelib.WidgetRedirector.

files:
  Lib/idlelib/WidgetRedirector.py |  78 ++++++++++++++++----
  1 files changed, 60 insertions(+), 18 deletions(-)


diff --git a/Lib/idlelib/WidgetRedirector.py b/Lib/idlelib/WidgetRedirector.py
--- 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 @@
     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 @@
                                              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 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 @@
         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 @@
     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)

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list