Merged revisions 66686 via svnmerge from

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.
........
This commit is contained in:
Martin v. Löwis 2008-09-29 22:19:08 +00:00
parent 28acc6cae5
commit 601149bb8e
4 changed files with 40 additions and 34 deletions

View File

@ -96,8 +96,8 @@ class DemoWindow(object):
left_frame.pack(side=LEFT, fill=BOTH, expand=0) left_frame.pack(side=LEFT, fill=BOTH, expand=0)
self.graph_frame = g_frame = Frame(root) self.graph_frame = g_frame = Frame(root)
turtle.Screen._root = g_frame turtle._Screen._root = g_frame
turtle.Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800) turtle._Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800)
#xturtle.Screen._canvas.pack(expand=1, fill="both") #xturtle.Screen._canvas.pack(expand=1, fill="both")
self.screen = _s_ = turtle.Screen() self.screen = _s_ = turtle.Screen()
##### #####

View 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 :class:`ScrolledCanvas` as argument. It should be used when :mod:`turtle` is
used as part of some application. used as part of some application.
Derived from :class:`TurtleScreen` is the subclass :class:`Screen`. Screen The function :func:`Screen` returns a singleton object of a
is implemented as sort of singleton, so there can exist only one instance of :class:`TurtleScreen` subclass. This function should be used when
Screen at a time. It should be used when :mod:`turtle` is used as a :mod:`turtle` is used as a standalone tool for doing graphics.
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 All methods of TurtleScreen/Screen also exist as functions, i.e. as part of
the procedure-oriented interface. the procedure-oriented interface.

View File

@ -2421,7 +2421,7 @@ class RawTurtle(TPen, TNavigator):
shape=_CFG["shape"], shape=_CFG["shape"],
undobuffersize=_CFG["undobuffersize"], undobuffersize=_CFG["undobuffersize"],
visible=_CFG["visible"]): visible=_CFG["visible"]):
if isinstance(canvas, Screen): if isinstance(canvas, _Screen):
self.screen = canvas self.screen = canvas
elif isinstance(canvas, TurtleScreen): elif isinstance(canvas, TurtleScreen):
if canvas not in RawTurtle.screens: if canvas not in RawTurtle.screens:
@ -3558,29 +3558,33 @@ class RawTurtle(TPen, TNavigator):
RawPen = RawTurtle 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 _root = None
_canvas = None _canvas = None
_title = _CFG["title"] _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): def __init__(self):
if Screen._root is None: # XXX there is no need for this code to be conditional,
Screen._root = self._root = _Root() # as there will be only a single _Screen instance, anyway
self._root.title(Screen._title) # 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) self._root.ondestroy(self._destroy)
if Screen._canvas is None: if _Screen._canvas is None:
width = _CFG["width"] width = _CFG["width"]
height = _CFG["height"] height = _CFG["height"]
canvwidth = _CFG["canvwidth"] canvwidth = _CFG["canvwidth"]
@ -3588,10 +3592,9 @@ class Screen(TurtleScreen):
leftright = _CFG["leftright"] leftright = _CFG["leftright"]
topbottom = _CFG["topbottom"] topbottom = _CFG["topbottom"]
self._root.setupcanvas(width, height, canvwidth, canvheight) self._root.setupcanvas(width, height, canvwidth, canvheight)
Screen._canvas = self._root._getcanvas() _Screen._canvas = self._root._getcanvas()
self.setup(width, height, leftright, topbottom) self.setup(width, height, leftright, topbottom)
TurtleScreen.__init__(self, Screen._canvas) TurtleScreen.__init__(self, _Screen._canvas)
Turtle._screen = self
def setup(self, width=_CFG["width"], height=_CFG["height"], def setup(self, width=_CFG["width"], height=_CFG["height"],
startx=_CFG["leftright"], starty=_CFG["topbottom"]): startx=_CFG["leftright"], starty=_CFG["topbottom"]):
@ -3645,17 +3648,17 @@ class Screen(TurtleScreen):
Example (for a Screen instance named screen): Example (for a Screen instance named screen):
>>> screen.title("Welcome to the turtle-zoo!") >>> screen.title("Welcome to the turtle-zoo!")
""" """
if Screen._root is not None: if _Screen._root is not None:
Screen._root.title(titlestring) _Screen._root.title(titlestring)
Screen._title = titlestring _Screen._title = titlestring
def _destroy(self): def _destroy(self):
root = self._root root = self._root
if root is Screen._root: if root is _Screen._root:
Turtle._pen = None Turtle._pen = None
Turtle._screen = None Turtle._screen = None
Screen._root = None _Screen._root = None
Screen._canvas = None _Screen._canvas = None
TurtleScreen._RUNNING = True TurtleScreen._RUNNING = True
root.destroy() root.destroy()
@ -3747,7 +3750,7 @@ def write_docstringdict(filename="turtle_docstringdict"):
docsdict = {} docsdict = {}
for methodname in _tg_screen_functions: for methodname in _tg_screen_functions:
key = "Screen."+methodname key = "_Screen."+methodname
docsdict[key] = eval(key).__doc__ docsdict[key] = eval(key).__doc__
for methodname in _tg_turtle_functions: for methodname in _tg_turtle_functions:
key = "Turtle."+methodname key = "Turtle."+methodname
@ -3862,7 +3865,7 @@ def _screen_docrevise(docstr):
for methodname in _tg_screen_functions: for methodname in _tg_screen_functions:
pl1, pl2 = getmethparlist(eval('Screen.' + methodname)) pl1, pl2 = getmethparlist(eval('_Screen.' + methodname))
if pl1 == "": if pl1 == "":
print(">>>>>>", pl1, pl2) print(">>>>>>", pl1, pl2)
continue continue
@ -3870,7 +3873,7 @@ for methodname in _tg_screen_functions:
{'key':methodname, 'pl1':pl1, 'pl2':pl2}) {'key':methodname, 'pl1':pl1, 'pl2':pl2})
## print("Screen:", defstr) ## print("Screen:", defstr)
exec(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: for methodname in _tg_turtle_functions:
pl1, pl2 = getmethparlist(eval('Turtle.' + methodname)) pl1, pl2 = getmethparlist(eval('Turtle.' + methodname))

View File

@ -22,6 +22,9 @@ Core and Builtins
Library 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 #3911: ftplib.FTP.makeport() could give invalid port numbers.
- Issue #3929: When the database cannot be opened, dbm.open() would incorrectly - Issue #3929: When the database cannot be opened, dbm.open() would incorrectly