]> granicus.if.org Git - python/commitdiff
Merged revisions 66686 via svnmerge from
authorMartin v. Löwis <martin@v.loewis.de>
Mon, 29 Sep 2008 22:19:08 +0000 (22:19 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Mon, 29 Sep 2008 22:19:08 +0000 (22:19 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r66686 | martin.v.loewis | 2008-09-30 00:09:07 +0200 (Di, 30 Sep 2008) | 5 lines

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

  Reviewed by Gregor Lingl.
........

Demo/turtle/turtleDemo.py
Doc/library/turtle.rst
Lib/turtle.py
Misc/NEWS

index b73daf090bddc16174358f4e1233d8eb830bb922..36bf15c7e539b6a3d9629b61fec03371939305dc 100644 (file)
@@ -96,8 +96,8 @@ class DemoWindow(object):
         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()
 #####
index 79297ebbdd2b8e8b2fd506192675032d8a2e1e8a..64df7421ce443fa5db2c90daa26b2a33d57094b2 100644 (file)
@@ -40,10 +40,10 @@ The object-oriented interface uses essentially two+two classes:
    :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.
index 1497d2d1239fba7080312472c85beba8a7fa3a8f..bcc53ce3dd5c44fae010e10942dc73e9fd23a8a6 100644 (file)
@@ -2421,7 +2421,7 @@ class RawTurtle(TPen, TNavigator):
                  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:
@@ -3558,29 +3558,33 @@ class RawTurtle(TPen, TNavigator):
 
 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"]
@@ -3588,10 +3592,9 @@ class Screen(TurtleScreen):
             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"]):
@@ -3645,17 +3648,17 @@ class Screen(TurtleScreen):
         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()
 
@@ -3747,7 +3750,7 @@ def write_docstringdict(filename="turtle_docstringdict"):
     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
@@ -3862,7 +3865,7 @@ def _screen_docrevise(docstr):
 
 
 for methodname in _tg_screen_functions:
-    pl1, pl2 = getmethparlist(eval('Screen.' + methodname))
+    pl1, pl2 = getmethparlist(eval('_Screen.' + methodname))
     if pl1 == "":
         print(">>>>>>", pl1, pl2)
         continue
@@ -3870,7 +3873,7 @@ for methodname in _tg_screen_functions:
                                    {'key':methodname, 'pl1':pl1, 'pl2':pl2})
 ##    print("Screen:", defstr)
     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))
index d4d0b42edcc65cba70f6a52f002ba9edf0358cc7..51206bdda412a67b8f5eee1ff11087e1bfa35f35 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #3965: Allow repeated calls to turtle.Screen, by making it a
+  true singleton object.
+
 - Issue #3911: ftplib.FTP.makeport() could give invalid port numbers.
 
 - Issue #3929: When the database cannot be opened, dbm.open() would incorrectly