[Python-checkins] cpython (2.7): Issue #6639: Module-level turtle functions no longer raise TclError after

serhiy.storchaka python-checkins at python.org
Sun Feb 22 16:28:06 CET 2015


https://hg.python.org/cpython/rev/15dd9d6cc632
changeset:   94722:15dd9d6cc632
branch:      2.7
parent:      94719:4d8e37e54a7d
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Sun Feb 22 17:22:53 2015 +0200
summary:
  Issue #6639: Module-level turtle functions no longer raise TclError after
closing the window.

files:
  Demo/turtle/turtleDemo.py |   4 +
  Lib/lib-tk/turtle.py      |  70 +++++++++++++-------------
  Misc/NEWS                 |   3 +
  3 files changed, 41 insertions(+), 36 deletions(-)


diff --git a/Demo/turtle/turtleDemo.py b/Demo/turtle/turtleDemo.py
--- a/Demo/turtle/turtleDemo.py
+++ b/Demo/turtle/turtleDemo.py
@@ -231,6 +231,8 @@
             else:
                 self.state = DONE
         except turtle.Terminator:
+            if self.root is None:
+                return
             self.state = DONE
             result = "stopped!"
         if self.state == DONE:
@@ -257,7 +259,9 @@
             turtle.TurtleScreen._RUNNING = False
 
     def _destroy(self):
+        turtle.TurtleScreen._RUNNING = False
         self.root.destroy()
+        self.root = None
         #sys.exit()
 
 def main():
diff --git a/Lib/lib-tk/turtle.py b/Lib/lib-tk/turtle.py
--- a/Lib/lib-tk/turtle.py
+++ b/Lib/lib-tk/turtle.py
@@ -1235,7 +1235,7 @@
     def _incrementudc(self):
         """Increment update counter."""
         if not TurtleScreen._RUNNING:
-            TurtleScreen._RUNNNING = True
+            TurtleScreen._RUNNING = True
             raise Terminator
         if self._tracing > 0:
             self._updatecounter += 1
@@ -3644,7 +3644,7 @@
             Turtle._screen = None
             _Screen._root = None
             _Screen._canvas = None
-        TurtleScreen._RUNNING = True
+        TurtleScreen._RUNNING = False
         root.destroy()
 
     def bye(self):
@@ -3685,7 +3685,6 @@
         except AttributeError:
             exit(0)
 
-
 class Turtle(RawTurtle):
     """RawTurtle auto-creating (scrolled) canvas.
 
@@ -3708,18 +3707,6 @@
 
 Pen = Turtle
 
-def _getpen():
-    """Create the 'anonymous' turtle if not already present."""
-    if Turtle._pen is None:
-        Turtle._pen = Turtle()
-    return Turtle._pen
-
-def _getscreen():
-    """Create a TurtleScreen if not already present."""
-    if Turtle._screen is None:
-        Turtle._screen = Screen()
-    return Turtle._screen
-
 def write_docstringdict(filename="turtle_docstringdict"):
     """Create and write docstring-dictionary to file.
 
@@ -3847,30 +3834,41 @@
 ## as functions. So we can enhance, change, add, delete methods to these
 ## classes and do not need to change anything here.
 
-
-for methodname in _tg_screen_functions:
-    pl1, pl2 = getmethparlist(eval('_Screen.' + methodname))
-    if pl1 == "":
-        print ">>>>>>", pl1, pl2
-        continue
-    defstr = ("def %(key)s%(pl1)s: return _getscreen().%(key)s%(pl2)s" %
-                                   {'key':methodname, 'pl1':pl1, 'pl2':pl2})
-    exec defstr
-    eval(methodname).__doc__ = _screen_docrevise(eval('_Screen.'+methodname).__doc__)
-
-for methodname in _tg_turtle_functions:
-    pl1, pl2 = getmethparlist(eval('Turtle.' + methodname))
-    if pl1 == "":
-        print ">>>>>>", pl1, pl2
-        continue
-    defstr = ("def %(key)s%(pl1)s: return _getpen().%(key)s%(pl2)s" %
-                                   {'key':methodname, 'pl1':pl1, 'pl2':pl2})
-    exec defstr
-    eval(methodname).__doc__ = _turtle_docrevise(eval('Turtle.'+methodname).__doc__)
+__func_body = """\
+def {name}{paramslist}:
+    if {obj} is None:
+        if not TurtleScreen._RUNNING:
+            TurtleScreen._RUNNING = True
+            raise Terminator
+        {obj} = {init}
+    try:
+        return {obj}.{name}{argslist}
+    except TK.TclError:
+        if not TurtleScreen._RUNNING:
+            TurtleScreen._RUNNING = True
+            raise Terminator
+        raise
+"""
+
+def _make_global_funcs(functions, cls, obj, init, docrevise):
+    for methodname in functions:
+        method = getattr(cls, methodname)
+        pl1, pl2 = getmethparlist(method)
+        if pl1 == "":
+            print ">>>>>>", pl1, pl2
+            continue
+        defstr = __func_body.format(obj=obj, init=init, name=methodname,
+                                    paramslist=pl1, argslist=pl2)
+        exec defstr in globals()
+        globals()[methodname].__doc__ = docrevise(method.__doc__)
+
+_make_global_funcs(_tg_screen_functions, _Screen,
+                   'Turtle._screen', 'Screen()', _screen_docrevise)
+_make_global_funcs(_tg_turtle_functions, Turtle,
+                   'Turtle._pen', 'Turtle()', _turtle_docrevise)
 
 
 done = mainloop = TK.mainloop
-del pl1, pl2, defstr
 
 if __name__ == "__main__":
     def switchpen():
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -116,6 +116,9 @@
 Tools/Demos
 -----------
 
+- Issue #6639: Module-level turtle functions no longer raise TclError after
+  closing the window.
+
 - Issue #22314: pydoc now works when the LINES environment variable is set.
 
 - Issue #18905: "pydoc -p 0" now outputs actually used port.  Based on patch by

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


More information about the Python-checkins mailing list