[Python-checkins] r66686 - in python/trunk: Demo/turtle/turtleDemo.py Doc/library/turtle.rst Lib/lib-tk/turtle.py Misc/NEWS

martin.v.loewis python-checkins at python.org
Tue Sep 30 00:09:07 CEST 2008


Author: martin.v.loewis
Date: Tue Sep 30 00:09:07 2008
New Revision: 66686

Log:
Issue #3965: Allow repeated calls to turtle.Screen, by making it a
true singleton object.

Reviewed by Gregor Lingl.


Modified:
   python/trunk/Demo/turtle/turtleDemo.py
   python/trunk/Doc/library/turtle.rst
   python/trunk/Lib/lib-tk/turtle.py
   python/trunk/Misc/NEWS

Modified: python/trunk/Demo/turtle/turtleDemo.py
==============================================================================
--- python/trunk/Demo/turtle/turtleDemo.py	(original)
+++ python/trunk/Demo/turtle/turtleDemo.py	Tue Sep 30 00:09:07 2008
@@ -94,8 +94,8 @@
         left_frame.pack(side=LEFT, fill=BOTH, expand=0)
         self.graph_frame = g_frame = Frame(root)
 
-        turtle.Screen._root = g_frame
-        turtle.Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800)
+        turtle._Screen._root = g_frame
+        turtle._Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800)
         #xturtle.Screen._canvas.pack(expand=1, fill="both")
         self.screen = _s_ = turtle.Screen()
         self.scanvas = _s_._canvas

Modified: python/trunk/Doc/library/turtle.rst
==============================================================================
--- python/trunk/Doc/library/turtle.rst	(original)
+++ python/trunk/Doc/library/turtle.rst	Tue Sep 30 00:09:07 2008
@@ -40,10 +40,10 @@
    :class:`ScrolledCanvas` as argument.  It should be used when :mod:`turtle` is
    used as part of some application.
 
-   Derived from :class:`TurtleScreen` is the subclass :class:`Screen`.  Screen
-   is implemented as sort of singleton, so there can exist only one instance of
-   Screen at a time.  It should be used when :mod:`turtle` is used as a
-   standalone tool for doing graphics.
+   The function :func:`Screen` returns a singleton object of a
+   :class:`TurtleScreen` subclass. This function should be used when
+   :mod:`turtle` is used as a standalone tool for doing graphics.
+   As a singleton object, inheriting from its class is not possible.
 
    All methods of TurtleScreen/Screen also exist as functions, i.e. as part of
    the procedure-oriented interface.

Modified: python/trunk/Lib/lib-tk/turtle.py
==============================================================================
--- python/trunk/Lib/lib-tk/turtle.py	(original)
+++ python/trunk/Lib/lib-tk/turtle.py	Tue Sep 30 00:09:07 2008
@@ -2422,7 +2422,7 @@
                  shape=_CFG["shape"],
                  undobuffersize=_CFG["undobuffersize"],
                  visible=_CFG["visible"]):
-        if isinstance(canvas, Screen):
+        if isinstance(canvas, _Screen):
             self.screen = canvas
         elif isinstance(canvas, TurtleScreen):
             if canvas not in RawTurtle.screens:
@@ -3539,29 +3539,33 @@
 
 RawPen = RawTurtle
 
-###  Screen - Klasse  ########################
+###  Screen - Singleton  ########################
 
-class Screen(TurtleScreen):
+def Screen():
+    """Return the singleton screen object.
+    If none exists at the moment, create a new one and return it,
+    else return the existing one."""
+    if Turtle._screen is None:
+        Turtle._screen = _Screen()
+    return Turtle._screen
+
+class _Screen(TurtleScreen):
 
     _root = None
     _canvas = None
     _title = _CFG["title"]
 
-    # Borg-Idiom
-
-    _shared_state = {}
-
-    def __new__(cls, *args, **kwargs):
-        obj = object.__new__(cls, *args, **kwargs)
-        obj.__dict__ = cls._shared_state
-        return obj
-
     def __init__(self):
-        if Screen._root is None:
-            Screen._root = self._root = _Root()
-            self._root.title(Screen._title)
+        # XXX there is no need for this code to be conditional,
+        # as there will be only a single _Screen instance, anyway
+        # XXX actually, the turtle demo is injecting root window,
+        # so perhaps the conditional creation of a root should be
+        # preserved (perhaps by passing it as an optional parameter)
+        if _Screen._root is None:
+            _Screen._root = self._root = _Root()
+            self._root.title(_Screen._title)
             self._root.ondestroy(self._destroy)
-        if Screen._canvas is None:
+        if _Screen._canvas is None:
             width = _CFG["width"]
             height = _CFG["height"]
             canvwidth = _CFG["canvwidth"]
@@ -3569,10 +3573,9 @@
             leftright = _CFG["leftright"]
             topbottom = _CFG["topbottom"]
             self._root.setupcanvas(width, height, canvwidth, canvheight)
-            Screen._canvas = self._root._getcanvas()
+            _Screen._canvas = self._root._getcanvas()
             self.setup(width, height, leftright, topbottom)
-        TurtleScreen.__init__(self, Screen._canvas)
-        Turtle._screen = self
+        TurtleScreen.__init__(self, _Screen._canvas)
 
     def setup(self, width=_CFG["width"], height=_CFG["height"],
               startx=_CFG["leftright"], starty=_CFG["topbottom"]):
@@ -3626,17 +3629,17 @@
         Example (for a Screen instance named screen):
         >>> screen.title("Welcome to the turtle-zoo!")
         """
-        if Screen._root is not None:
-            Screen._root.title(titlestring)
-        Screen._title = titlestring
+        if _Screen._root is not None:
+            _Screen._root.title(titlestring)
+        _Screen._title = titlestring
 
     def _destroy(self):
         root = self._root
-        if root is Screen._root:
+        if root is _Screen._root:
             Turtle._pen = None
             Turtle._screen = None
-            Screen._root = None
-            Screen._canvas = None
+            _Screen._root = None
+            _Screen._canvas = None
         TurtleScreen._RUNNING = True
         root.destroy()
 
@@ -3728,7 +3731,7 @@
     docsdict = {}
 
     for methodname in _tg_screen_functions:
-        key = "Screen."+methodname
+        key = "_Screen."+methodname
         docsdict[key] = eval(key).__doc__
     for methodname in _tg_turtle_functions:
         key = "Turtle."+methodname
@@ -3842,14 +3845,14 @@
 
 
 for methodname in _tg_screen_functions:
-    pl1, pl2 = getmethparlist(eval('Screen.' + methodname))
+    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__)
+    eval(methodname).__doc__ = _screen_docrevise(eval('_Screen.'+methodname).__doc__)
 
 for methodname in _tg_turtle_functions:
     pl1, pl2 = getmethparlist(eval('Turtle.' + methodname))

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Tue Sep 30 00:09:07 2008
@@ -23,6 +23,9 @@
 Library
 -------
 
+- Issue #3965: Allow repeated calls to turtle.Screen, by making it a
+  true singleton object.
+
 - Issue #3895: It was possible to crash the interpreter when an external timer
   was used with cProfile that returned an object that could not be converted
   into a float.


More information about the Python-checkins mailing list