xsywa 发表于 2021-2-19 11:00:01

turtle

本帖最后由 xsywa 于 2021-2-19 11:09 编辑

都是turtle是内置库,可我的怎么用不了
尤其按照网上的教程再重新安装,点不开turtle.py

逃兵 发表于 2021-2-19 11:05:28

打错了
import

xsywa 发表于 2021-2-19 11:06:33

逃兵 发表于 2021-2-19 11:05
打错了
import

额,这个没注意,改了后也是一样的

来自星星的小明 发表于 2021-2-19 13:40:47

你的python是什么版本的,你下载的该包是否在模块路径中,麻烦详细描述一下问题

考不好不改名 发表于 2021-2-19 14:03:39

本帖最后由 考不好不改名 于 2021-2-19 14:05 编辑

建议重装Python

考不好不改名 发表于 2021-2-19 14:08:29

你找到你Python安装的目录(默认是C:\Users\33260\AppData\Local\Programs\Python);在目录下打开Lib,看看有没有一个叫turtle.py的文件;如果没有,新建一个同名文件,并打开输入以下代码:_ver = "turtle 1.1b- - for Python 3.1   -4. 5. 2009"

import tkinter as TK
import types
import math
import time
import inspect
import sys

from os.path import isfile, split, join
from copy import deepcopy
from tkinter import simpledialog

_tg_classes = ['ScrolledCanvas', 'TurtleScreen', 'Screen',
               'RawTurtle', 'Turtle', 'RawPen', 'Pen', 'Shape', 'Vec2D']
_tg_screen_functions = ['addshape', 'bgcolor', 'bgpic', 'bye',
      'clearscreen', 'colormode', 'delay', 'exitonclick', 'getcanvas',
      'getshapes', 'listen', 'mainloop', 'mode', 'numinput',
      'onkey', 'onkeypress', 'onkeyrelease', 'onscreenclick', 'ontimer',
      'register_shape', 'resetscreen', 'screensize', 'setup',
      'setworldcoordinates', 'textinput', 'title', 'tracer', 'turtles', 'update',
      'window_height', 'window_width']
_tg_turtle_functions = ['back', 'backward', 'begin_fill', 'begin_poly', 'bk',
      'circle', 'clear', 'clearstamp', 'clearstamps', 'clone', 'color',
      'degrees', 'distance', 'dot', 'down', 'end_fill', 'end_poly', 'fd',
      'fillcolor', 'filling', 'forward', 'get_poly', 'getpen', 'getscreen', 'get_shapepoly',
      'getturtle', 'goto', 'heading', 'hideturtle', 'home', 'ht', 'isdown',
      'isvisible', 'left', 'lt', 'onclick', 'ondrag', 'onrelease', 'pd',
      'pen', 'pencolor', 'pendown', 'pensize', 'penup', 'pos', 'position',
      'pu', 'radians', 'right', 'reset', 'resizemode', 'rt',
      'seth', 'setheading', 'setpos', 'setposition', 'settiltangle',
      'setundobuffer', 'setx', 'sety', 'shape', 'shapesize', 'shapetransform', 'shearfactor', 'showturtle',
      'speed', 'st', 'stamp', 'tilt', 'tiltangle', 'towards',
      'turtlesize', 'undo', 'undobufferentries', 'up', 'width',
      'write', 'xcor', 'ycor']
_tg_utilities = ['write_docstringdict', 'done']

__all__ = (_tg_classes + _tg_screen_functions + _tg_turtle_functions +
         _tg_utilities + ['Terminator']) # + _math_functions)

_alias_list = ['addshape', 'backward', 'bk', 'fd', 'ht', 'lt', 'pd', 'pos',
               'pu', 'rt', 'seth', 'setpos', 'setposition', 'st',
               'turtlesize', 'up', 'width']

_CFG = {"width" : 0.5,               # Screen
      "height" : 0.75,
      "canvwidth" : 400,
      "canvheight": 300,
      "leftright": None,
      "topbottom": None,
      "mode": "standard",          # TurtleScreen
      "colormode": 1.0,
      "delay": 10,
      "undobuffersize": 1000,      # RawTurtle
      "shape": "classic",
      "pencolor" : "black",
      "fillcolor" : "black",
      "resizemode" : "noresize",
      "visible" : True,
      "language": "english",      # docstrings
      "exampleturtle": "turtle",
      "examplescreen": "screen",
      "title": "Python Turtle Graphics",
      "using_IDLE": False
       }

def config_dict(filename):
    with open(filename, "r") as f:
      cfglines = f.readlines()
    cfgdict = {}
    for line in cfglines:
      line = line.strip()
      if not line or line.startswith("#"):
            continue
      try:
            key, value = line.split("=")
      except ValueError:
            print("Bad line in config-file %s:\n%s" % (filename,line))
            continue
      key = key.strip()
      value = value.strip()
      if value in ["True", "False", "None", "''", '""']:
            value = eval(value)
      else:
            try:
                if "." in value:
                  value = float(value)
                else:
                  value = int(value)
            except ValueError:
                pass # value need not be converted
      cfgdict = value
    return cfgdict

def readconfig(cfgdict):
    default_cfg = "turtle.cfg"
    cfgdict1 = {}
    cfgdict2 = {}
    if isfile(default_cfg):
      cfgdict1 = config_dict(default_cfg)
    if "importconfig" in cfgdict1:
      default_cfg = "turtle_%s.cfg" % cfgdict1["importconfig"]
    try:
      head, tail = split(__file__)
      cfg_file2 = join(head, default_cfg)
    except Exception:
      cfg_file2 = ""
    if isfile(cfg_file2):
      cfgdict2 = config_dict(cfg_file2)
    _CFG.update(cfgdict2)
    _CFG.update(cfgdict1)

try:
    readconfig(_CFG)
except Exception:
    print ("No configfile read, reason unknown")


class Vec2D(tuple):
    def __new__(cls, x, y):
      return tuple.__new__(cls, (x, y))
    def __add__(self, other):
      return Vec2D(self+other, self+other)
    def __mul__(self, other):
      if isinstance(other, Vec2D):
            return self*other+self*other
      return Vec2D(self*other, self*other)
    def __rmul__(self, other):
      if isinstance(other, int) or isinstance(other, float):
            return Vec2D(self*other, self*other)
      return NotImplemented
    def __sub__(self, other):
      return Vec2D(self-other, self-other)
    def __neg__(self):
      return Vec2D(-self, -self)
    def __abs__(self):
      return (self**2 + self**2)**0.5
    def rotate(self, angle):
      """rotate self counterclockwise by angle
      """
      perp = Vec2D(-self, self)
      angle = angle * math.pi / 180.0
      c, s = math.cos(angle), math.sin(angle)
      return Vec2D(self*c+perp*s, self*c+perp*s)
    def __getnewargs__(self):
      return (self, self)
    def __repr__(self):
      return "(%.2f,%.2f)" % self

def __methodDict(cls, _dict):
    """helper function for Scrolled Canvas"""
    baseList = list(cls.__bases__)
    baseList.reverse()
    for _super in baseList:
      __methodDict(_super, _dict)
    for key, value in cls.__dict__.items():
      if type(value) == types.FunctionType:
            _dict = value

def __methods(cls):
    """helper function for Scrolled Canvas"""
    _dict = {}
    __methodDict(cls, _dict)
    return _dict.keys()

__stringBody = (
    'def %(method)s(self, *args, **kw): return ' +
    'self.%(attribute)s.%(method)s(*args, **kw)')

def __forwardmethods(fromClass, toClass, toPart, exclude = ()):
    ### MANY CHANGES ###
    _dict_1 = {}
    __methodDict(toClass, _dict_1)
    _dict = {}
    mfc = __methods(fromClass)
    for ex in _dict_1.keys():
      if ex[:1] == '_' or ex[-1:] == '_' or ex in exclude or ex in mfc:
            pass
      else:
            _dict = _dict_1

    for method, func in _dict.items():
      d = {'method': method, 'func': func}
      if isinstance(toPart, str):
            execString = \
                __stringBody % {'method' : method, 'attribute' : toPart}
      exec(execString, d)
      setattr(fromClass, method, d)   ### NEWU!


class ScrolledCanvas(TK.Frame):
    """Modeled after the scrolled canvas class from Grayons's Tkinter book.

    Used as the default canvas, which pops up automatically when
    using turtle graphics functions or the Turtle class.
    """
    def __init__(self, master, width=500, height=350,
                                          canvwidth=600, canvheight=500):
      TK.Frame.__init__(self, master, width=width, height=height)
      self._rootwindow = self.winfo_toplevel()
      self.width, self.height = width, height
      self.canvwidth, self.canvheight = canvwidth, canvheight
      self.bg = "white"
      self._canvas = TK.Canvas(master, width=width, height=height,
                                 bg=self.bg, relief=TK.SUNKEN, borderwidth=2)
      self.hscroll = TK.Scrollbar(master, command=self._canvas.xview,
                                    orient=TK.HORIZONTAL)
      self.vscroll = TK.Scrollbar(master, command=self._canvas.yview)
      self._canvas.configure(xscrollcommand=self.hscroll.set,
                               yscrollcommand=self.vscroll.set)
      self.rowconfigure(0, weight=1, minsize=0)
      self.columnconfigure(0, weight=1, minsize=0)
      self._canvas.grid(padx=1, in_ = self, pady=1, row=0,
                column=0, rowspan=1, columnspan=1, sticky='news')
      self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
                column=1, rowspan=1, columnspan=1, sticky='news')
      self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
                column=0, rowspan=1, columnspan=1, sticky='news')
      self.reset()
      self._rootwindow.bind('<Configure>', self.onResize)

    def reset(self, canvwidth=None, canvheight=None, bg = None):
      """Adjust canvas and scrollbars according to given canvas size."""
      if canvwidth:
            self.canvwidth = canvwidth
      if canvheight:
            self.canvheight = canvheight
      if bg:
            self.bg = bg
      self._canvas.config(bg=bg,
                        scrollregion=(-self.canvwidth//2, -self.canvheight//2,
                                       self.canvwidth//2, self.canvheight//2))
      self._canvas.xview_moveto(0.5*(self.canvwidth - self.width + 30) /
                                                               self.canvwidth)
      self._canvas.yview_moveto(0.5*(self.canvheight- self.height + 30) /
                                                            self.canvheight)
      self.adjustScrolls()


    def adjustScrolls(self):
      """ Adjust scrollbars according to window- and canvas-size.
      """
      cwidth = self._canvas.winfo_width()
      cheight = self._canvas.winfo_height()
      self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth)
      self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight)
      if cwidth < self.canvwidth or cheight < self.canvheight:
            self.hscroll.grid(padx=1, in_ = self, pady=1, row=1,
                              column=0, rowspan=1, columnspan=1, sticky='news')
            self.vscroll.grid(padx=1, in_ = self, pady=1, row=0,
                              column=1, rowspan=1, columnspan=1, sticky='news')
      else:
            self.hscroll.grid_forget()
            self.vscroll.grid_forget()

    def onResize(self, event):
      """self-explanatory"""
      self.adjustScrolls()

    def bbox(self, *args):
      """ 'forward' method, which canvas itself has inherited...
      """
      return self._canvas.bbox(*args)

    def cget(self, *args, **kwargs):
      """ 'forward' method, which canvas itself has inherited...
      """
      return self._canvas.cget(*args, **kwargs)

    def config(self, *args, **kwargs):
      """ 'forward' method, which canvas itself has inherited...
      """
      self._canvas.config(*args, **kwargs)

    def bind(self, *args, **kwargs):
      """ 'forward' method, which canvas itself has inherited...
      """
      self._canvas.bind(*args, **kwargs)

    def unbind(self, *args, **kwargs):
      """ 'forward' method, which canvas itself has inherited...
      """
      self._canvas.unbind(*args, **kwargs)

    def focus_force(self):
      """ 'forward' method, which canvas itself has inherited...
      """
      self._canvas.focus_force()

__forwardmethods(ScrolledCanvas, TK.Canvas, '_canvas')


class _Root(TK.Tk):
    """Root class for Screen based on Tkinter."""
    def __init__(self):
      TK.Tk.__init__(self)

    def setupcanvas(self, width, height, cwidth, cheight):
      self._canvas = ScrolledCanvas(self, width, height, cwidth, cheight)
      self._canvas.pack(expand=1, fill="both")

    def _getcanvas(self):
      return self._canvas

    def set_geometry(self, width, height, startx, starty):
      self.geometry("%dx%d%+d%+d"%(width, height, startx, starty))

    def ondestroy(self, destroy):
      self.wm_protocol("WM_DELETE_WINDOW", destroy)

    def win_width(self):
      return self.winfo_screenwidth()

    def win_height(self):
      return self.winfo_screenheight()

Canvas = TK.Canvas


class TurtleScreenBase(object):
    @staticmethod
    def _blankimage():
      """return a blank image object
      """
      img = TK.PhotoImage(width=1, height=1)
      img.blank()
      return img

    @staticmethod
    def _image(filename):
      """return an image object containing the
      imagedata from a gif-file named filename.
      """
      return TK.PhotoImage(file=filename)

    def __init__(self, cv):
      self.cv = cv
      if isinstance(cv, ScrolledCanvas):
            w = self.cv.canvwidth
            h = self.cv.canvheight
      else:# expected: ordinary TK.Canvas
            w = int(self.cv.cget("width"))
            h = int(self.cv.cget("height"))
            self.cv.config(scrollregion = (-w//2, -h//2, w//2, h//2 ))
      self.canvwidth = w
      self.canvheight = h
      self.xscale = self.yscale = 1.0

    def _createpoly(self):
      """Create an invisible polygon item on canvas self.cv)
      """
      return self.cv.create_polygon((0, 0, 0, 0, 0, 0), fill="", outline="")

    def _drawpoly(self, polyitem, coordlist, fill=None,
                  outline=None, width=None, top=False):
      cl = []
      for x, y in coordlist:
            cl.append(x * self.xscale)
            cl.append(-y * self.yscale)
      self.cv.coords(polyitem, *cl)
      if fill is not None:
            self.cv.itemconfigure(polyitem, fill=fill)
      if outline is not None:
            self.cv.itemconfigure(polyitem, outline=outline)
      if width is not None:
            self.cv.itemconfigure(polyitem, width=width)
      if top:
            self.cv.tag_raise(polyitem)

    def _createline(self):
      """Create an invisible line item on canvas self.cv)
      """
      return self.cv.create_line(0, 0, 0, 0, fill="", width=2,
                                 capstyle = TK.ROUND)

    def _drawline(self, lineitem, coordlist=None,
                  fill=None, width=None, top=False):
      if coordlist is not None:
            cl = []
            for x, y in coordlist:
                cl.append(x * self.xscale)
                cl.append(-y * self.yscale)
            self.cv.coords(lineitem, *cl)
      if fill is not None:
            self.cv.itemconfigure(lineitem, fill=fill)
      if width is not None:
            self.cv.itemconfigure(lineitem, width=width)
      if top:
            self.cv.tag_raise(lineitem)

    def _delete(self, item):
      self.cv.delete(item)

    def _update(self):
      """Redraw graphics items on canvas
      """
      self.cv.update()

    def _delay(self, delay):
      """Delay subsequent canvas actions for delay ms."""
      self.cv.after(delay)

    def _iscolorstring(self, color):
      """Check if the string color is a legal Tkinter color string.
      """
      try:
            rgb = self.cv.winfo_rgb(color)
            ok = True
      except TK.TclError:
            ok = False
      return ok

    def _bgcolor(self, color=None):
      if color is not None:
            self.cv.config(bg = color)
            self._update()
      else:
            return self.cv.cget("bg")

    def _write(self, pos, txt, align, font, pencolor):
      x, y = pos
      x = x * self.xscale
      y = y * self.yscale
      anchor = {"left":"sw", "center":"s", "right":"se" }
      item = self.cv.create_text(x-1, -y, text = txt, anchor = anchor,
                                        fill = pencolor, font = font)
      x0, y0, x1, y1 = self.cv.bbox(item)
      self.cv.update()
      return item, x1-1

##    def _dot(self, pos, size, color):
##      """may be implemented for some other graphics toolkit"""

    def _onclick(self, item, fun, num=1, add=None):
      """Bind fun to mouse-click event on turtle.
      fun must be a function with two arguments, the coordinates
      of the clicked point on the canvas.
      num, the number of the mouse-button defaults to 1
      """
      if fun is None:
            self.cv.tag_unbind(item, "<Button-%s>" % num)
      else:
            def eventfun(event):
                x, y = (self.cv.canvasx(event.x)/self.xscale,
                        -self.cv.canvasy(event.y)/self.yscale)
                fun(x, y)
            self.cv.tag_bind(item, "<Button-%s>" % num, eventfun, add)

    def _onrelease(self, item, fun, num=1, add=None):
      if fun is None:
            self.cv.tag_unbind(item, "<Button%s-ButtonRelease>" % num)
      else:
            def eventfun(event):
                x, y = (self.cv.canvasx(event.x)/self.xscale,
                        -self.cv.canvasy(event.y)/self.yscale)
                fun(x, y)
            self.cv.tag_bind(item, "<Button%s-ButtonRelease>" % num,
                           eventfun, add)

    def _ondrag(self, item, fun, num=1, add=None):
      """Bind fun to mouse-move-event (with pressed mouse button) on turtle.
      fun must be a function with two arguments, the coordinates of the
      actual mouse position on the canvas.
      num, the number of the mouse-button defaults to 1

      Every sequence of mouse-move-events on a turtle is preceded by a
      mouse-click event on that turtle.
      """
      if fun is None:
            self.cv.tag_unbind(item, "<Button%s-Motion>" % num)
      else:
            def eventfun(event):
                try:
                  x, y = (self.cv.canvasx(event.x)/self.xscale,
                           -self.cv.canvasy(event.y)/self.yscale)
                  fun(x, y)
                except Exception:
                  pass
            self.cv.tag_bind(item, "<Button%s-Motion>" % num, eventfun, add)

    def _onscreenclick(self, fun, num=1, add=None):
      if fun is None:
            self.cv.unbind("<Button-%s>" % num)
      else:
            def eventfun(event):
                x, y = (self.cv.canvasx(event.x)/self.xscale,
                        -self.cv.canvasy(event.y)/self.yscale)
                fun(x, y)
            self.cv.bind("<Button-%s>" % num, eventfun, add)

    def _onkeyrelease(self, fun, key):
      """Bind fun to key-release event of key.
      Canvas must have focus. See method listen
      """
      if fun is None:
            self.cv.unbind("<KeyRelease-%s>" % key, None)
      else:
            def eventfun(event):
                fun()
            self.cv.bind("<KeyRelease-%s>" % key, eventfun)

    def _onkeypress(self, fun, key=None):
      """If key is given, bind fun to key-press event of key.
      Otherwise bind fun to any key-press.
      Canvas must have focus. See method listen.
      """
      if fun is None:
            if key is None:
                self.cv.unbind("<KeyPress>", None)
            else:
                self.cv.unbind("<KeyPress-%s>" % key, None)
      else:
            def eventfun(event):
                fun()
            if key is None:
                self.cv.bind("<KeyPress>", eventfun)
            else:
                self.cv.bind("<KeyPress-%s>" % key, eventfun)

    def _listen(self):
      """Set focus on canvas (in order to collect key-events)
      """
      self.cv.focus_force()

    def _ontimer(self, fun, t):
      """Install a timer, which calls fun after t milliseconds.
      """
      if t == 0:
            self.cv.after_idle(fun)
      else:
            self.cv.after(t, fun)

    def _createimage(self, image):
      """Create and return image item on canvas.
      """
      return self.cv.create_image(0, 0, image=image)

    def _drawimage(self, item, pos, image):
      """Configure image item as to draw image object
      at position (x,y) on canvas)
      """
      x, y = pos
      self.cv.coords(item, (x * self.xscale, -y * self.yscale))
      self.cv.itemconfig(item, image=image)

    def _setbgpic(self, item, image):
      """Configure image item as to draw image object
      at center of canvas. Set item to the first item
      in the displaylist, so it will be drawn below
      any other item ."""
      self.cv.itemconfig(item, image=image)
      self.cv.tag_lower(item)

    def _type(self, item):
      """Return 'line' or 'polygon' or 'image' depending on
      type of item.
      """
      return self.cv.type(item)

    def _pointlist(self, item):
      """returns list of coordinate-pairs of points of item
      Example (for insiders):
      >>> from turtle import *
      >>> getscreen()._pointlist(getturtle().turtle._item)
      [(0.0, 9.9999999999999982), (0.0, -9.9999999999999982),
      (9.9999999999999982, 0.0)]
      >>> """
      cl = self.cv.coords(item)
      pl = [(cl, -cl) for i in range(0, len(cl), 2)]
      returnpl

    def _setscrollregion(self, srx1, sry1, srx2, sry2):
      self.cv.config(scrollregion=(srx1, sry1, srx2, sry2))

    def _rescale(self, xscalefactor, yscalefactor):
      items = self.cv.find_all()
      for item in items:
            coordinates = list(self.cv.coords(item))
            newcoordlist = []
            while coordinates:
                x, y = coordinates[:2]
                newcoordlist.append(x * xscalefactor)
                newcoordlist.append(y * yscalefactor)
                coordinates = coordinates
            self.cv.coords(item, *newcoordlist)

    def _resize(self, canvwidth=None, canvheight=None, bg=None):
      """Resize the canvas the turtles are drawing on. Does
      not alter the drawing window.
      """
      # needs amendment
      if not isinstance(self.cv, ScrolledCanvas):
            return self.canvwidth, self.canvheight
      if canvwidth is canvheight is bg is None:
            return self.cv.canvwidth, self.cv.canvheight
      if canvwidth is not None:
            self.canvwidth = canvwidth
      if canvheight is not None:
            self.canvheight = canvheight
      self.cv.reset(canvwidth, canvheight, bg)

    def _window_size(self):
      """ Return the width and height of the turtle window.
      """
      width = self.cv.winfo_width()
      if width <= 1:
            width = self.cv['width']
      height = self.cv.winfo_height()
      if height <= 1:
            height = self.cv['height']
      return width, height

    def mainloop(self):
      TK.mainloop()

    def textinput(self, title, prompt):
      return simpledialog.askstring(title, prompt)

    def numinput(self, title, prompt, default=None, minval=None, maxval=None):
      return simpledialog.askfloat(title, prompt, initialvalue=default,
                                     minvalue=minval, maxvalue=maxval)

class Terminator (Exception):
    pass


class TurtleGraphicsError(Exception):
    """Some TurtleGraphics Error
    """


class Shape(object):
    def __init__(self, type_, data=None):
      self._type = type_
      if type_ == "polygon":
            if isinstance(data, list):
                data = tuple(data)
      elif type_ == "image":
            if isinstance(data, str):
                if data.lower().endswith(".gif") and isfile(data):
                  data = TurtleScreen._image(data)
                # else data assumed to be Photoimage
      elif type_ == "compound":
            data = []
      else:
            raise TurtleGraphicsError("There is no shape type %s" % type_)
      self._data = data

    def addcomponent(self, poly, fill, outline=None):
      if self._type != "compound":
            raise TurtleGraphicsError("Cannot add component to %s Shape"
                                                                % self._type)
      if outline is None:
            outline = fill
      self._data.append()


class Tbuffer(object):
    """Ring buffer used as undobuffer for RawTurtle objects."""
    def __init__(self, bufsize=10):
      self.bufsize = bufsize
      self.buffer = [] * bufsize
      self.ptr = -1
      self.cumulate = False
    def reset(self, bufsize=None):
      if bufsize is None:
            for i in range(self.bufsize):
                self.buffer =
      else:
            self.bufsize = bufsize
            self.buffer = [] * bufsize
      self.ptr = -1
    def push(self, item):
      if self.bufsize > 0:
            if not self.cumulate:
                self.ptr = (self.ptr + 1) % self.bufsize
                self.buffer = item
            else:
                self.buffer.append(item)
    def pop(self):
      if self.bufsize > 0:
            item = self.buffer
            if item is None:
                return None
            else:
                self.buffer =
                self.ptr = (self.ptr - 1) % self.bufsize
                return (item)
    def nr_of_items(self):
      return self.bufsize - self.buffer.count()
    def __repr__(self):
      return str(self.buffer) + " " + str(self.ptr)



class TurtleScreen(TurtleScreenBase):
    _RUNNING = True

    def __init__(self, cv, mode=_CFG["mode"],
               colormode=_CFG["colormode"], delay=_CFG["delay"]):
      self._shapes = {
                   "arrow" : Shape("polygon", ((-10,0), (10,0), (0,10))),
                  "turtle" : Shape("polygon", ((0,16), (-2,14), (-1,10), (-4,7),
                              (-7,9), (-9,8), (-6,5), (-7,1), (-5,-3), (-8,-6),
                              (-6,-8), (-4,-5), (0,-7), (4,-5), (6,-8), (8,-6),
                              (5,-3), (7,1), (6,5), (9,8), (7,9), (4,7), (1,10),
                              (2,14))),
                  "circle" : Shape("polygon", ((10,0), (9.51,3.09), (8.09,5.88),
                              (5.88,8.09), (3.09,9.51), (0,10), (-3.09,9.51),
                              (-5.88,8.09), (-8.09,5.88), (-9.51,3.09), (-10,0),
                              (-9.51,-3.09), (-8.09,-5.88), (-5.88,-8.09),
                              (-3.09,-9.51), (-0.00,-10.00), (3.09,-9.51),
                              (5.88,-8.09), (8.09,-5.88), (9.51,-3.09))),
                  "square" : Shape("polygon", ((10,-10), (10,10), (-10,10),
                              (-10,-10))),
                "triangle" : Shape("polygon", ((10,-5.77), (0,11.55),
                              (-10,-5.77))),
                  "classic": Shape("polygon", ((0,0),(-5,-9),(0,-7),(5,-9))),
                   "blank" : Shape("image", self._blankimage())
                  }

      self._bgpics = {"nopic" : ""}

      TurtleScreenBase.__init__(self, cv)
      self._mode = mode
      self._delayvalue = delay
      self._colormode = _CFG["colormode"]
      self._keys = []
      self.clear()
      if sys.platform == 'darwin':
            rootwindow = cv.winfo_toplevel()
            rootwindow.call('wm', 'attributes', '.', '-topmost', '1')
            rootwindow.call('wm', 'attributes', '.', '-topmost', '0')

    def clear(self):
      self._delayvalue = _CFG["delay"]
      self._colormode = _CFG["colormode"]
      self._delete("all")
      self._bgpic = self._createimage("")
      self._bgpicname = "nopic"
      self._tracing = 1
      self._updatecounter = 0
      self._turtles = []
      self.bgcolor("white")
      for btn in 1, 2, 3:
            self.onclick(None, btn)
      self.onkeypress(None)
      for key in self._keys[:]:
            self.onkey(None, key)
            self.onkeypress(None, key)
      Turtle._pen = None

    def mode(self, mode=None):
      if mode is None:
            return self._mode
      mode = mode.lower()
      if mode not in ["standard", "logo", "world"]:
            raise TurtleGraphicsError("No turtle-graphics-mode %s" % mode)
      self._mode = mode
      if mode in ["standard", "logo"]:
            self._setscrollregion(-self.canvwidth//2, -self.canvheight//2,
                                       self.canvwidth//2, self.canvheight//2)
            self.xscale = self.yscale = 1.0
      self.reset()

    def setworldcoordinates(self, llx, lly, urx, ury):
      if self.mode() != "world":
            self.mode("world")
      xspan = float(urx - llx)
      yspan = float(ury - lly)
      wx, wy = self._window_size()
      self.screensize(wx-20, wy-20)
      oldxscale, oldyscale = self.xscale, self.yscale
      self.xscale = self.canvwidth / xspan
      self.yscale = self.canvheight / yspan
      srx1 = llx * self.xscale
      sry1 = -ury * self.yscale
      srx2 = self.canvwidth + srx1
      sry2 = self.canvheight + sry1
      self._setscrollregion(srx1, sry1, srx2, sry2)
      self._rescale(self.xscale/oldxscale, self.yscale/oldyscale)
      self.update()

    def register_shape(self, name, shape=None):
      if shape is None:
            # image
            if name.lower().endswith(".gif"):
                shape = Shape("image", self._image(name))
            else:
                raise TurtleGraphicsError("Bad arguments for register_shape.\n"
                                          + "Usehelp(register_shape)" )
      elif isinstance(shape, tuple):
            shape = Shape("polygon", shape)
      ## else shape assumed to be Shape-instance
      self._shapes = shape

    def _colorstr(self, color):
      if len(color) == 1:
            color = color
      if isinstance(color, str):
            if self._iscolorstring(color) or color == "":
                return color
            else:
                raise TurtleGraphicsError("bad color string: %s" % str(color))
      try:
            r, g, b = color
      except (TypeError, ValueError):
            raise TurtleGraphicsError("bad color arguments: %s" % str(color))
      if self._colormode == 1.0:
            r, g, b =
      if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
            raise TurtleGraphicsError("bad color sequence: %s" % str(color))
      return "#%02x%02x%02x" % (r, g, b)

    def _color(self, cstr):
      if not cstr.startswith("#"):
            return cstr
      if len(cstr) == 7:
            cl = , 16) for i in (1, 3, 5)]
      elif len(cstr) == 4:
            cl = , 16) for h in cstr]
      else:
            raise TurtleGraphicsError("bad colorstring: %s" % cstr)
      return tuple(c * self._colormode/255 for c in cl)

    def colormode(self, cmode=None):
      if cmode is None:
            return self._colormode
      if cmode == 1.0:
            self._colormode = float(cmode)
      elif cmode == 255:
            self._colormode = int(cmode)

    def reset(self):
      for turtle in self._turtles:
            turtle._setmode(self._mode)
            turtle.reset()

    def turtles(self):
      return self._turtles

    def bgcolor(self, *args):
      if args:
            color = self._colorstr(args)
      else:
            color = None
      color = self._bgcolor(color)
      if color is not None:
            color = self._color(color)
      return color

    def tracer(self, n=None, delay=None):
      if n is None:
            return self._tracing
      self._tracing = int(n)
      self._updatecounter = 0
      if delay is not None:
            self._delayvalue = int(delay)
      if self._tracing:
            self.update()

    def delay(self, delay=None):
      if delay is None:
            return self._delayvalue
      self._delayvalue = int(delay)

    def _incrementudc(self):
      """Increment update counter."""
      if not TurtleScreen._RUNNING:
            TurtleScreen._RUNNING = True
            raise Terminator
      if self._tracing > 0:
            self._updatecounter += 1
            self._updatecounter %= self._tracing

    def update(self):
      """Perform a TurtleScreen update.
      """
      tracing = self._tracing
      self._tracing = True
      for t in self.turtles():
            t._update_data()
            t._drawturtle()
      self._tracing = tracing
      self._update()

    def window_width(self):
      return self._window_size()

    def window_height(self):
      return self._window_size()

    def getcanvas(self):
      return self.cv

    def getshapes(self):
      return sorted(self._shapes.keys())

    def onclick(self, fun, btn=1, add=None):
      self._onscreenclick(fun, btn, add)

    def onkey(self, fun, key):
      if fun is None:
            if key in self._keys:
                self._keys.remove(key)
      elif key not in self._keys:
            self._keys.append(key)
      self._onkeyrelease(fun, key)

    def onkeypress(self, fun, key=None):
      if fun is None:
            if key in self._keys:
                self._keys.remove(key)
      elif key is not None and key not in self._keys:
            self._keys.append(key)
      self._onkeypress(fun, key)

    def listen(self, xdummy=None, ydummy=None):
      self._listen()

    def ontimer(self, fun, t=0):
      self._ontimer(fun, t)

    def bgpic(self, picname=None):
      if picname is None:
            return self._bgpicname
      if picname not in self._bgpics:
            self._bgpics = self._image(picname)
      self._setbgpic(self._bgpic, self._bgpics)
      self._bgpicname = picname

    def screensize(self, canvwidth=None, canvheight=None, bg=None):
      return self._resize(canvwidth, canvheight, bg)

    onscreenclick = onclick
    resetscreen = reset
    clearscreen = clear
    addshape = register_shape
    onkeyrelease = onkey

class TNavigator(object):
    """Navigation part of the RawTurtle.
    Implements methods for turtle movement.
    """
    START_ORIENTATION = {
      "standard": Vec2D(1.0, 0.0),
      "world"   : Vec2D(1.0, 0.0),
      "logo"    : Vec2D(0.0, 1.0)}
    DEFAULT_MODE = "standard"
    DEFAULT_ANGLEOFFSET = 0
    DEFAULT_ANGLEORIENT = 1

    def __init__(self, mode=DEFAULT_MODE):
      self._angleOffset = self.DEFAULT_ANGLEOFFSET
      self._angleOrient = self.DEFAULT_ANGLEORIENT
      self._mode = mode
      self.undobuffer = None
      self.degrees()
      self._mode = None
      self._setmode(mode)
      TNavigator.reset(self)

    def reset(self):
      self._position = Vec2D(0.0, 0.0)
      self._orient =TNavigator.START_ORIENTATION

    def _setmode(self, mode=None):
      """Set turtle-mode to 'standard', 'world' or 'logo'.
      """
      if mode is None:
            return self._mode
      if mode not in ["standard", "logo", "world"]:
            return
      self._mode = mode
      if mode in ["standard", "world"]:
            self._angleOffset = 0
            self._angleOrient = 1
      else: # mode == "logo":
            self._angleOffset = self._fullcircle/4.
            self._angleOrient = -1

    def _setDegreesPerAU(self, fullcircle):
      """Helper function for degrees() and radians()"""
      self._fullcircle = fullcircle
      self._degreesPerAU = 360/fullcircle
      if self._mode == "standard":
            self._angleOffset = 0
      else:
            self._angleOffset = fullcircle/4.

    def degrees(self, fullcircle=360.0):
      self._setDegreesPerAU(fullcircle)

    def radians(self):
      self._setDegreesPerAU(2*math.pi)

    def _go(self, distance):
      """move turtle forward by specified distance"""
      ende = self._position + self._orient * distance
      self._goto(ende)

    def _rotate(self, angle):
      """Turn turtle counterclockwise by specified angle if angle > 0."""
      angle *= self._degreesPerAU
      self._orient = self._orient.rotate(angle)

    def _goto(self, end):
      """move turtle to position end."""
      self._position = end

    def forward(self, distance):
      self._go(distance)

    def back(self, distance):
      self._go(-distance)

    def right(self, angle):
      self._rotate(-angle)

    def left(self, angle):
      self._rotate(angle)

    def pos(self):
      return self._position

    def xcor(self):
      return self._position

    def ycor(self):
      return self._position


    def goto(self, x, y=None):
      if y is None:
            self._goto(Vec2D(*x))
      else:
            self._goto(Vec2D(x, y))

    def home(self):
      self.goto(0, 0)
      self.setheading(0)

    def setx(self, x):
      self._goto(Vec2D(x, self._position))

    def sety(self, y):
      self._goto(Vec2D(self._position, y))

    def distance(self, x, y=None):
      if y is not None:
            pos = Vec2D(x, y)
      if isinstance(x, Vec2D):
            pos = x
      elif isinstance(x, tuple):
            pos = Vec2D(*x)
      elif isinstance(x, TNavigator):
            pos = x._position
      return abs(pos - self._position)

    def towards(self, x, y=None):
      if y is not None:
            pos = Vec2D(x, y)
      if isinstance(x, Vec2D):
            pos = x
      elif isinstance(x, tuple):
            pos = Vec2D(*x)
      elif isinstance(x, TNavigator):
            pos = x._position
      x, y = pos - self._position
      result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
      result /= self._degreesPerAU
      return (self._angleOffset + self._angleOrient*result) % self._fullcircle

    def heading(self):
      x, y = self._orient
      result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0
      result /= self._degreesPerAU
      return (self._angleOffset + self._angleOrient*result) % self._fullcircle

    def setheading(self, to_angle):
      angle = (to_angle - self.heading())*self._angleOrient
      full = self._fullcircle
      angle = (angle+full/2.)%full - full/2.
      self._rotate(angle)

    def circle(self, radius, extent = None, steps = None):
      if self.undobuffer:
            self.undobuffer.push(["seq"])
            self.undobuffer.cumulate = True
      speed = self.speed()
      if extent is None:
            extent = self._fullcircle
      if steps is None:
            frac = abs(extent)/self._fullcircle
            steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac)
      w = 1.0 * extent / steps
      w2 = 0.5 * w
      l = 2.0 * radius * math.sin(w2*math.pi/180.0*self._degreesPerAU)
      if radius < 0:
            l, w, w2 = -l, -w, -w2
      tr = self._tracer()
      dl = self._delay()
      if speed == 0:
            self._tracer(0, 0)
      else:
            self.speed(0)
      self._rotate(w2)
      for i in range(steps):
            self.speed(speed)
            self._go(l)
            self.speed(0)
            self._rotate(w)
      self._rotate(-w2)
      if speed == 0:
            self._tracer(tr, dl)
      self.speed(speed)
      if self.undobuffer:
            self.undobuffer.cumulate = False

## three dummy methods to be implemented by child class:

    def speed(self, s=0):
      """dummy method - to be overwritten by child class"""
    def _tracer(self, a=None, b=None):
      """dummy method - to be overwritten by child class"""
    def _delay(self, n=None):
      """dummy method - to be overwritten by child class"""

    fd = forward
    bk = back
    backward = back
    rt = right
    lt = left
    position = pos
    setpos = goto
    setposition = goto
    seth = setheading


class TPen(object):
    def __init__(self, resizemode=_CFG["resizemode"]):
      self._resizemode = resizemode # or "user" or "noresize"
      self.undobuffer = None
      TPen._reset(self)

    def _reset(self, pencolor=_CFG["pencolor"],
                     fillcolor=_CFG["fillcolor"]):
      self._pensize = 1
      self._shown = True
      self._pencolor = pencolor
      self._fillcolor = fillcolor
      self._drawing = True
      self._speed = 3
      self._stretchfactor = (1., 1.)
      self._shearfactor = 0.
      self._tilt = 0.
      self._shapetrafo = (1., 0., 0., 1.)
      self._outlinewidth = 1

    def resizemode(self, rmode=None):
      if rmode is None:
            return self._resizemode
      rmode = rmode.lower()
      if rmode in ["auto", "user", "noresize"]:
            self.pen(resizemode=rmode)

    def pensize(self, width=None):
      if width is None:
            return self._pensize
      self.pen(pensize=width)


    def penup(self):
      if not self._drawing:
            return
      self.pen(pendown=False)

    def pendown(self):
      if self._drawing:
            return
      self.pen(pendown=True)

    def isdown(self):
      return self._drawing

    def speed(self, speed=None):
      speeds = {'fastest':0, 'fast':10, 'normal':6, 'slow':3, 'slowest':1 }
      if speed is None:
            return self._speed
      if speed in speeds:
            speed = speeds
      elif 0.5 < speed < 10.5:
            speed = int(round(speed))
      else:
            speed = 0
      self.pen(speed=speed)

    def color(self, *args):
      if args:
            l = len(args)
            if l == 1:
                pcolor = fcolor = args
            elif l == 2:
                pcolor, fcolor = args
            elif l == 3:
                pcolor = fcolor = args
            pcolor = self._colorstr(pcolor)
            fcolor = self._colorstr(fcolor)
            self.pen(pencolor=pcolor, fillcolor=fcolor)
      else:
            return self._color(self._pencolor), self._color(self._fillcolor)

    def pencolor(self, *args):
      if args:
            color = self._colorstr(args)
            if color == self._pencolor:
                return
            self.pen(pencolor=color)
      else:
            return self._color(self._pencolor)

    def fillcolor(self, *args):
      if args:
            color = self._colorstr(args)
            if color == self._fillcolor:
                return
            self.pen(fillcolor=color)
      else:
            return self._color(self._fillcolor)

    def showturtle(self):
      self.pen(shown=True)

    def hideturtle(self):
      self.pen(shown=False)

    def isvisible(self):
      return self._shown

    def pen(self, pen=None, **pendict):
      _pd ={"shown"         : self._shown,
                "pendown"       : self._drawing,
                "pencolor"      : self._pencolor,
                "fillcolor"   : self._fillcolor,
                "pensize"       : self._pensize,
                "speed"         : self._speed,
                "resizemode"    : self._resizemode,
                "stretchfactor" : self._stretchfactor,
                "shearfactor"   : self._shearfactor,
                "outline"       : self._outlinewidth,
                "tilt"          : self._tilt
               }

      if not (pen or pendict):
            return _pd

      if isinstance(pen, dict):
            p = pen
      else:
            p = {}
      p.update(pendict)

      _p_buf = {}
      for key in p:
            _p_buf = _pd

      if self.undobuffer:
            self.undobuffer.push(("pen", _p_buf))

      newLine = False
      if "pendown" in p:
            if self._drawing != p["pendown"]:
                newLine = True
      if "pencolor" in p:
            if isinstance(p["pencolor"], tuple):
                p["pencolor"] = self._colorstr((p["pencolor"],))
            if self._pencolor != p["pencolor"]:
                newLine = True
      if "pensize" in p:
            if self._pensize != p["pensize"]:
                newLine = True
      if newLine:
            self._newLine()
      if "pendown" in p:
            self._drawing = p["pendown"]
      if "pencolor" in p:
            self._pencolor = p["pencolor"]
      if "pensize" in p:
            self._pensize = p["pensize"]
      if "fillcolor" in p:
            if isinstance(p["fillcolor"], tuple):
                p["fillcolor"] = self._colorstr((p["fillcolor"],))
            self._fillcolor = p["fillcolor"]
      if "speed" in p:
            self._speed = p["speed"]
      if "resizemode" in p:
            self._resizemode = p["resizemode"]
      if "stretchfactor" in p:
            sf = p["stretchfactor"]
            if isinstance(sf, (int, float)):
                sf = (sf, sf)
            self._stretchfactor = sf
      if "shearfactor" in p:
            self._shearfactor = p["shearfactor"]
      if "outline" in p:
            self._outlinewidth = p["outline"]
      if "shown" in p:
            self._shown = p["shown"]
      if "tilt" in p:
            self._tilt = p["tilt"]
      if "stretchfactor" in p or "tilt" in p or "shearfactor" in p:
            scx, scy = self._stretchfactor
            shf = self._shearfactor
            sa, ca = math.sin(self._tilt), math.cos(self._tilt)
            self._shapetrafo = ( scx*ca, scy*(shf*ca + sa),
                              -scx*sa, scy*(ca - shf*sa))
      self._update()

## three dummy methods to be implemented by child class:

    def _newLine(self, usePos = True):
      """dummy method - to be overwritten by child class"""
    def _update(self, count=True, forced=False):
      """dummy method - to be overwritten by child class"""
    def _color(self, args):
      """dummy method - to be overwritten by child class"""
    def _colorstr(self, args):
      """dummy method - to be overwritten by child class"""

    width = pensize
    up = penup
    pu = penup
    pd = pendown
    down = pendown
    st = showturtle
    ht = hideturtle


class _TurtleImage(object):
    """Helper class: Datatype to store Turtle attributes
    """

    def __init__(self, screen, shapeIndex):
      self.screen = screen
      self._type = None
      self._setshape(shapeIndex)

    def _setshape(self, shapeIndex):
      screen = self.screen
      self.shapeIndex = shapeIndex
      if self._type == "polygon" == screen._shapes._type:
            return
      if self._type == "image" == screen._shapes._type:
            return
      if self._type in ["image", "polygon"]:
            screen._delete(self._item)
      elif self._type == "compound":
            for item in self._item:
                screen._delete(item)
      self._type = screen._shapes._type
      if self._type == "polygon":
            self._item = screen._createpoly()
      elif self._type == "image":
            self._item = screen._createimage(screen._shapes["blank"]._data)
      elif self._type == "compound":
            self._item = [screen._createpoly() for item in
                                          screen._shapes._data]


class RawTurtle(TPen, TNavigator):
    """Animation part of the RawTurtle.
    Puts RawTurtle upon a TurtleScreen and provides tools for
    its animation.
    """
    screens = []

    def __init__(self, canvas=None,
               shape=_CFG["shape"],
               undobuffersize=_CFG["undobuffersize"],
               visible=_CFG["visible"]):
      if isinstance(canvas, _Screen):
            self.screen = canvas
      elif isinstance(canvas, TurtleScreen):
            if canvas not in RawTurtle.screens:
                RawTurtle.screens.append(canvas)
            self.screen = canvas
      elif isinstance(canvas, (ScrolledCanvas, Canvas)):
            for screen in RawTurtle.screens:
                if screen.cv == canvas:
                  self.screen = screen
                  break
            else:
                self.screen = TurtleScreen(canvas)
                RawTurtle.screens.append(self.screen)
      else:
            raise TurtleGraphicsError("bad canvas argument %s" % canvas)

      screen = self.screen
      TNavigator.__init__(self, screen.mode())
      TPen.__init__(self)
      screen._turtles.append(self)
      self.drawingLineItem = screen._createline()
      self.turtle = _TurtleImage(screen, shape)
      self._poly = None
      self._creatingPoly = False
      self._fillitem = self._fillpath = None
      self._shown = visible
      self._hidden_from_screen = False
      self.currentLineItem = screen._createline()
      self.currentLine =
      self.items =
      self.stampItems = []
      self._undobuffersize = undobuffersize
      self.undobuffer = Tbuffer(undobuffersize)
      self._update()

    def reset(self):
      """Delete the turtle's drawings and restore its default values.

      No argument.

      Delete the turtle's drawings from the screen, re-center the turtle
      and set variables to the default values.

      Example (for a Turtle instance named turtle):
      >>> turtle.position()
      (0.00,-22.00)
      >>> turtle.heading()
      100.0
      >>> turtle.reset()
      >>> turtle.position()
      (0.00,0.00)
      >>> turtle.heading()
      0.0
      """
      TNavigator.reset(self)
      TPen._reset(self)
      self._clear()
      self._drawturtle()
      self._update()

    def setundobuffer(self, size):
      """Set or disable undobuffer.

      Argument:
      size -- an integer or None

      If size is an integer an empty undobuffer of given size is installed.
      Size gives the maximum number of turtle-actions that can be undone
      by the undo() function.
      If size is None, no undobuffer is present.

      Example (for a Turtle instance named turtle):
      >>> turtle.setundobuffer(42)
      """
      if size is None or size <= 0:
            self.undobuffer = None
      else:
            self.undobuffer = Tbuffer(size)

    def undobufferentries(self):
      """Return count of entries in the undobuffer.

      No argument.

      Example (for a Turtle instance named turtle):
      >>> while undobufferentries():
      ...   undo()
      """
      if self.undobuffer is None:
            return 0
      return self.undobuffer.nr_of_items()

    def _clear(self):
      """Delete all of pen's drawings"""
      self._fillitem = self._fillpath = None
      for item in self.items:
            self.screen._delete(item)
      self.currentLineItem = self.screen._createline()
      self.currentLine = []
      if self._drawing:
            self.currentLine.append(self._position)
      self.items =
      self.clearstamps()
      self.setundobuffer(self._undobuffersize)


    def clear(self):
      """Delete the turtle's drawings from the screen. Do not move turtle.

      No arguments.

      Delete the turtle's drawings from the screen. Do not move turtle.
      State and position of the turtle as well as drawings of other
      turtles are not affected.

      Examples (for a Turtle instance named turtle):
      >>> turtle.clear()
      """
      self._clear()
      self._update()

    def _update_data(self):
      self.screen._incrementudc()
      if self.screen._updatecounter != 0:
            return
      if len(self.currentLine)>1:
            self.screen._drawline(self.currentLineItem, self.currentLine,
                                  self._pencolor, self._pensize)

    def _update(self):
      """Perform a Turtle-data update.
      """
      screen = self.screen
      if screen._tracing == 0:
            return
      elif screen._tracing == 1:
            self._update_data()
            self._drawturtle()
            screen._update()                  # TurtleScreenBase
            screen._delay(screen._delayvalue) # TurtleScreenBase
      else:
            self._update_data()
            if screen._updatecounter == 0:
                for t in screen.turtles():
                  t._drawturtle()
                screen._update()

    def _tracer(self, flag=None, delay=None):
      """Turns turtle animation on/off and set delay for update drawings.

      Optional arguments:
      n -- nonnegativeinteger
      delay -- nonnegativeinteger

      If n is given, only each n-th regular screen update is really performed.
      (Can be used to accelerate the drawing of complex graphics.)
      Second arguments sets delay value (see RawTurtle.delay())

      Example (for a Turtle instance named turtle):
      >>> turtle.tracer(8, 25)
      >>> dist = 2
      >>> for i in range(200):
      ...   turtle.fd(dist)
      ...   turtle.rt(90)
      ...   dist += 2
      """
      return self.screen.tracer(flag, delay)

    def _color(self, args):
      return self.screen._color(args)

    def _colorstr(self, args):
      return self.screen._colorstr(args)

    def _cc(self, args):
      """Convert colortriples to hexstrings.
      """
      if isinstance(args, str):
            return args
      try:
            r, g, b = args
      except (TypeError, ValueError):
            raise TurtleGraphicsError("bad color arguments: %s" % str(args))
      if self.screen._colormode == 1.0:
            r, g, b =
      if not ((0 <= r <= 255) and (0 <= g <= 255) and (0 <= b <= 255)):
            raise TurtleGraphicsError("bad color sequence: %s" % str(args))
      return "#%02x%02x%02x" % (r, g, b)

    def clone(self):
      """Create and return a clone of the turtle.

      No argument.

      Create and return a clone of the turtle with same position, heading
      and turtle properties.

      Example (for a Turtle instance named mick):
      mick = Turtle()
      joe = mick.clone()
      """
      screen = self.screen
      self._newLine(self._drawing)

      turtle = self.turtle
      self.screen = None
      self.turtle = None# too make self deepcopy-able

      q = deepcopy(self)

      self.screen = screen
      self.turtle = turtle

      q.screen = screen
      q.turtle = _TurtleImage(screen, self.turtle.shapeIndex)

      screen._turtles.append(q)
      ttype = screen._shapes._type
      if ttype == "polygon":
            q.turtle._item = screen._createpoly()
      elif ttype == "image":
            q.turtle._item = screen._createimage(screen._shapes["blank"]._data)
      elif ttype == "compound":
            q.turtle._item = [screen._createpoly() for item in
                              screen._shapes._data]
      q.currentLineItem = screen._createline()
      q._update()
      return q

    def shape(self, name=None):
      """Set turtle shape to shape with given name / return current shapename.

      Optional argument:
      name -- a string, which is a valid shapename

      Set turtle shape to shape with given name or, if name is not given,
      return name of current shape.
      Shape with name must exist in the TurtleScreen's shape dictionary.
      Initially there are the following polygon shapes:
      'arrow', 'turtle', 'circle', 'square', 'triangle', 'classic'.
      To learn about how to deal with shapes see Screen-method register_shape.

      Example (for a Turtle instance named turtle):
      >>> turtle.shape()
      'arrow'
      >>> turtle.shape("turtle")
      >>> turtle.shape()
      'turtle'
      """
      if name is None:
            return self.turtle.shapeIndex
      if not name in self.screen.getshapes():
            raise TurtleGraphicsError("There is no shape named %s" % name)
      self.turtle._setshape(name)
      self._update()

    def shapesize(self, stretch_wid=None, stretch_len=None, outline=None):
      """Set/return turtle's stretchfactors/outline. Set resizemode to "user".

      Optional arguments:
         stretch_wid : positive number
         stretch_len : positive number
         outline: positive number

      Return or set the pen's attributes x/y-stretchfactors and/or outline.
      Set resizemode to "user".
      If and only if resizemode is set to "user", the turtle will be displayed
      stretched according to its stretchfactors:
      stretch_wid is stretchfactor perpendicular to orientation
      stretch_len is stretchfactor in direction of turtles orientation.
      outline determines the width of the shapes's outline.

      Examples (for a Turtle instance named turtle):
      >>> turtle.resizemode("user")
      >>> turtle.shapesize(5, 5, 12)
      >>> turtle.shapesize(outline=8)
      """
      if stretch_wid is stretch_len is outline is None:
            stretch_wid, stretch_len = self._stretchfactor
            return stretch_wid, stretch_len, self._outlinewidth
      if stretch_wid == 0 or stretch_len == 0:
            raise TurtleGraphicsError("stretch_wid/stretch_len must not be zero")
      if stretch_wid is not None:
            if stretch_len is None:
                stretchfactor = stretch_wid, stretch_wid
            else:
                stretchfactor = stretch_wid, stretch_len
      elif stretch_len is not None:
            stretchfactor = self._stretchfactor, stretch_len
      else:
            stretchfactor = self._stretchfactor
      if outline is None:
            outline = self._outlinewidth
      self.pen(resizemode="user",
               stretchfactor=stretchfactor, outline=outline)

    def shearfactor(self, shear=None):
      if shear is None:
            return self._shearfactor
      self.pen(resizemode="user", shearfactor=shear)

    def settiltangle(self, angle):
      tilt = -angle * self._degreesPerAU * self._angleOrient
      tilt = (tilt * math.pi / 180.0) % (2*math.pi)
      self.pen(resizemode="user", tilt=tilt)

    def tiltangle(self, angle=None):
      if angle is None:
            tilt = -self._tilt * (180.0/math.pi) * self._angleOrient
            return (tilt / self._degreesPerAU) % self._fullcircle
      else:
            self.settiltangle(angle)

    def tilt(self, angle):
      self.settiltangle(angle + self.tiltangle())

    def shapetransform(self, t11=None, t12=None, t21=None, t22=None):
      if t11 is t12 is t21 is t22 is None:
            return self._shapetrafo
      m11, m12, m21, m22 = self._shapetrafo
      if t11 is not None: m11 = t11
      if t12 is not None: m12 = t12
      if t21 is not None: m21 = t21
      if t22 is not None: m22 = t22
      if t11 * t22 - t12 * t21 == 0:
            raise TurtleGraphicsError("Bad shape transform matrix: must not be singular")
      self._shapetrafo = (m11, m12, m21, m22)
      alfa = math.atan2(-m21, m11) % (2 * math.pi)
      sa, ca = math.sin(alfa), math.cos(alfa)
      a11, a12, a21, a22 = (ca*m11 - sa*m21, ca*m12 - sa*m22,
                              sa*m11 + ca*m21, sa*m12 + ca*m22)
      self._stretchfactor = a11, a22
      self._shearfactor = a12/a22
      self._tilt = alfa
      self.pen(resizemode="user")


    def _polytrafo(self, poly):
      """Computes transformed polygon shapes from a shape
      according to current position and heading.
      """
      screen = self.screen
      p0, p1 = self._position
      e0, e1 = self._orient
      e = Vec2D(e0, e1 * screen.yscale / screen.xscale)
      e0, e1 = (1.0 / abs(e)) * e
      return [(p0+(e1*x+e0*y)/screen.xscale, p1+(-e0*x+e1*y)/screen.yscale)
                                                         for (x, y) in poly]

    def get_shapepoly(self):
      shape = self.screen._shapes
      if shape._type == "polygon":
            return self._getshapepoly(shape._data, shape._type == "compound")
      # else return None

    def _getshapepoly(self, polygon, compound=False):
      """Calculate transformed shape polygon according to resizemode
      and shapetransform.
      """
      if self._resizemode == "user" or compound:
            t11, t12, t21, t22 = self._shapetrafo
      elif self._resizemode == "auto":
            l = max(1, self._pensize/5.0)
            t11, t12, t21, t22 = l, 0, 0, l
      elif self._resizemode == "noresize":
            return polygon
      return tuple((t11*x + t12*y, t21*x + t22*y) for (x, y) in polygon)

    def _drawturtle(self):
      """Manages the correct rendering of the turtle with respect to
      its shape, resizemode, stretch and tilt etc."""
      screen = self.screen
      shape = screen._shapes
      ttype = shape._type
      titem = self.turtle._item
      if self._shown and screen._updatecounter == 0 and screen._tracing > 0:
            self._hidden_from_screen = False
            tshape = shape._data
            if ttype == "polygon":
                if self._resizemode == "noresize": w = 1
                elif self._resizemode == "auto": w = self._pensize
                else: w =self._outlinewidth
                shape = self._polytrafo(self._getshapepoly(tshape))
                fc, oc = self._fillcolor, self._pencolor
                screen._drawpoly(titem, shape, fill=fc, outline=oc,
                                                      width=w, top=True)
            elif ttype == "image":
                screen._drawimage(titem, self._position, tshape)
            elif ttype == "compound":
                for item, (poly, fc, oc) in zip(titem, tshape):
                  poly = self._polytrafo(self._getshapepoly(poly, True))
                  screen._drawpoly(item, poly, fill=self._cc(fc),
                                     outline=self._cc(oc), width=self._outlinewidth, top=True)
      else:
            if self._hidden_from_screen:
                return
            if ttype == "polygon":
                screen._drawpoly(titem, ((0, 0), (0, 0), (0, 0)), "", "")
            elif ttype == "image":
                screen._drawimage(titem, self._position,
                                          screen._shapes["blank"]._data)
            elif ttype == "compound":
                for item in titem:
                  screen._drawpoly(item, ((0, 0), (0, 0), (0, 0)), "", "")
            self._hidden_from_screen = True

##############################stamp stuff###############################

    def stamp(self):
      screen = self.screen
      shape = screen._shapes
      ttype = shape._type
      tshape = shape._data
      if ttype == "polygon":
            stitem = screen._createpoly()
            if self._resizemode == "noresize": w = 1
            elif self._resizemode == "auto": w = self._pensize
            else: w =self._outlinewidth
            shape = self._polytrafo(self._getshapepoly(tshape))
            fc, oc = self._fillcolor, self._pencolor
            screen._drawpoly(stitem, shape, fill=fc, outline=oc,
                                                width=w, top=True)
      elif ttype == "image":
            stitem = screen._createimage("")
            screen._drawimage(stitem, self._position, tshape)
      elif ttype == "compound":
            stitem = []
            for element in tshape:
                item = screen._createpoly()
                stitem.append(item)
            stitem = tuple(stitem)
            for item, (poly, fc, oc) in zip(stitem, tshape):
                poly = self._polytrafo(self._getshapepoly(poly, True))
                screen._drawpoly(item, poly, fill=self._cc(fc),
                                 outline=self._cc(oc), width=self._outlinewidth, top=True)
      self.stampItems.append(stitem)
      self.undobuffer.push(("stamp", stitem))
      return stitem

    def _clearstamp(self, stampid):
      """does the work for clearstamp() and clearstamps()
      """
      if stampid in self.stampItems:
            if isinstance(stampid, tuple):
                for subitem in stampid:
                  self.screen._delete(subitem)
            else:
                self.screen._delete(stampid)
            self.stampItems.remove(stampid)
      # Delete stampitem from undobuffer if necessary
      # if clearstamp is called directly.
      item = ("stamp", stampid)
      buf = self.undobuffer
      if item not in buf.buffer:
            return
      index = buf.buffer.index(item)
      buf.buffer.remove(item)
      if index <= buf.ptr:
            buf.ptr = (buf.ptr - 1) % buf.bufsize
      buf.buffer.insert((buf.ptr+1)%buf.bufsize, )

    def clearstamp(self, stampid):
      self._clearstamp(stampid)
      self._update()

    def clearstamps(self, n=None):
      if n is None:
            toDelete = self.stampItems[:]
      elif n >= 0:
            toDelete = self.stampItems[:n]
      else:
            toDelete = self.stampItems
      for item in toDelete:
            self._clearstamp(item)
      self._update()

    def _goto(self, end):
      """Move the pen to the point end, thereby drawing a line
      if pen is down. All other methods for turtle movement depend
      on this one.
      """
      ## Version with undo-stuff
      go_modes = ( self._drawing,
                     self._pencolor,
                     self._pensize,
                     isinstance(self._fillpath, list))
      screen = self.screen
      undo_entry = ("go", self._position, end, go_modes,
                      (self.currentLineItem,
                      self.currentLine[:],
                      screen._pointlist(self.currentLineItem),
                      self.items[:])
                      )
      if self.undobuffer:
            self.undobuffer.push(undo_entry)
      start = self._position
      if self._speed and screen._tracing == 1:
            diff = (end-start)
            diffsq = (diff*screen.xscale)**2 + (diff*screen.yscale)**2
            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
            delta = diff * (1.0/nhops)
            for n in range(1, nhops):
                if n == 1:
                  top = True
                else:
                  top = False
                self._position = start + delta * n
                if self._drawing:
                  screen._drawline(self.drawingLineItem,
                                     (start, self._position),
                                     self._pencolor, self._pensize, top)
                self._update()
            if self._drawing:
                screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
                                             fill="", width=self._pensize)
      # Turtle now at end,
      if self._drawing: # now update currentLine
            self.currentLine.append(end)
      if isinstance(self._fillpath, list):
            self._fillpath.append(end)
      ######    vererbung!!!!!!!!!!!!!!!!!!!!!!
      self._position = end
      if self._creatingPoly:
            self._poly.append(end)
      if len(self.currentLine) > 42: # 42! answer to the ultimate question
                                       # of life, the universe and everything
            self._newLine()
      self._update() #count=True)

    def _undogoto(self, entry):
      """Reverse a _goto. Used for undo()
      """
      old, new, go_modes, coodata = entry
      drawing, pc, ps, filling = go_modes
      cLI, cL, pl, items = coodata
      screen = self.screen
      if abs(self._position - new) > 0.5:
            print ("undogoto: HALLO-DA-STIMMT-WAS-NICHT!")
      # restore former situation
      self.currentLineItem = cLI
      self.currentLine = cL

      if pl == [(0, 0), (0, 0)]:
            usepc = ""
      else:
            usepc = pc
      screen._drawline(cLI, pl, fill=usepc, width=ps)

      todelete = [i for i in self.items if (i not in items) and
                                       (screen._type(i) == "line")]
      for i in todelete:
            screen._delete(i)
            self.items.remove(i)

      start = old
      if self._speed and screen._tracing == 1:
            diff = old - new
            diffsq = (diff*screen.xscale)**2 + (diff*screen.yscale)**2
            nhops = 1+int((diffsq**0.5)/(3*(1.1**self._speed)*self._speed))
            delta = diff * (1.0/nhops)
            for n in range(1, nhops):
                if n == 1:
                  top = True
                else:
                  top = False
                self._position = new + delta * n
                if drawing:
                  screen._drawline(self.drawingLineItem,
                                     (start, self._position),
                                     pc, ps, top)
                self._update()
            if drawing:
                screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
                                             fill="", width=ps)
      # Turtle now at position old,
      self._position = old

      if self._creatingPoly:
            if len(self._poly) > 0:
                self._poly.pop()
            if self._poly == []:
                self._creatingPoly = False
                self._poly = None
      if filling:
            if self._fillpath == []:
                self._fillpath = None
                print("Unwahrscheinlich in _undogoto!")
            elif self._fillpath is not None:
                self._fillpath.pop()
      self._update() #count=True)

    def _rotate(self, angle):
      """Turns pen clockwise by angle.
      """
      if self.undobuffer:
            self.undobuffer.push(("rot", angle, self._degreesPerAU))
      angle *= self._degreesPerAU
      neworient = self._orient.rotate(angle)
      tracing = self.screen._tracing
      if tracing == 1 and self._speed > 0:
            anglevel = 3.0 * self._speed
            steps = 1 + int(abs(angle)/anglevel)
            delta = 1.0*angle/steps
            for _ in range(steps):
                self._orient = self._orient.rotate(delta)
                self._update()
      self._orient = neworient
      self._update()

    def _newLine(self, usePos=True):
      if len(self.currentLine) > 1:
            self.screen._drawline(self.currentLineItem, self.currentLine,
                                    self._pencolor, self._pensize)
            self.currentLineItem = self.screen._createline()
            self.items.append(self.currentLineItem)
      else:
            self.screen._drawline(self.currentLineItem, top=True)
      self.currentLine = []
      if usePos:
            self.currentLine =

    def filling(self):
      """Return fillstate (True if filling, False else).

      No argument.

      Example (for a Turtle instance named turtle):
      >>> turtle.begin_fill()
      >>> if turtle.filling():
      ...   turtle.pensize(5)
      ... else:
      ...   turtle.pensize(3)
      """
      return isinstance(self._fillpath, list)

    def begin_fill(self):
      if not self.filling():
            self._fillitem = self.screen._createpoly()
            self.items.append(self._fillitem)
      self._fillpath =
      self._newLine()
      if self.undobuffer:
            self.undobuffer.push(("beginfill", self._fillitem))
      self._update()


    def end_fill(self):
      """Fill the shape drawn after the call begin_fill().

      No argument.

      Example (for a Turtle instance named turtle):
      >>> turtle.color("black", "red")
      >>> turtle.begin_fill()
      >>> turtle.circle(60)
      >>> turtle.end_fill()
      """
      if self.filling():
            if len(self._fillpath) > 2:
                self.screen._drawpoly(self._fillitem, self._fillpath,
                                    fill=self._fillcolor)
                if self.undobuffer:
                  self.undobuffer.push(("dofill", self._fillitem))
            self._fillitem = self._fillpath = None
            self._update()

    def dot(self, size=None, *color):
      if not color:
            if isinstance(size, (str, tuple)):
                color = self._colorstr(size)
                size = self._pensize + max(self._pensize, 4)
            else:
                color = self._pencolor
                if not size:
                  size = self._pensize + max(self._pensize, 4)
      else:
            if size is None:
                size = self._pensize + max(self._pensize, 4)
            color = self._colorstr(color)
      if hasattr(self.screen, "_dot"):
            item = self.screen._dot(self._position, size, color)
            self.items.append(item)
            if self.undobuffer:
                self.undobuffer.push(("dot", item))
      else:
            pen = self.pen()
            if self.undobuffer:
                self.undobuffer.push(["seq"])
                self.undobuffer.cumulate = True
            try:
                if self.resizemode() == 'auto':
                  self.ht()
                self.pendown()
                self.pensize(size)
                self.pencolor(color)
                self.forward(0)
            finally:
                self.pen(pen)
            if self.undobuffer:
                self.undobuffer.cumulate = False

    def _write(self, txt, align, font):
      """Performs the writing for write()
      """
      item, end = self.screen._write(self._position, txt, align, font,
                                                          self._pencolor)
      self.items.append(item)
      if self.undobuffer:
            self.undobuffer.push(("wri", item))
      return end

    def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")):
      if self.undobuffer:
            self.undobuffer.push(["seq"])
            self.undobuffer.cumulate = True
      end = self._write(str(arg), align.lower(), font)
      if move:
            x, y = self.pos()
            self.setpos(end, y)
      if self.undobuffer:
            self.undobuffer.cumulate = False

    def begin_poly(self):
      """Start recording the vertices of a polygon.

      No argument.

      Start recording the vertices of a polygon. Current turtle position
      is first point of polygon.

      Example (for a Turtle instance named turtle):
      >>> turtle.begin_poly()
      """
      self._poly =
      self._creatingPoly = True

    def end_poly(self):
      self._creatingPoly = False

    def get_poly(self):
      """Return the lastly recorded polygon.

      No argument.

      Example (for a Turtle instance named turtle):
      >>> p = turtle.get_poly()
      >>> turtle.register_shape("myFavouriteShape", p)
      """
      ## check if there is any poly?
      if self._poly is not None:
            return tuple(self._poly)

    def getscreen(self):
      return self.screen

    def getturtle(self):
      """Return the Turtleobject itself.

      No argument.

      Only reasonable use: as a function to return the 'anonymous turtle':

      Example:
      >>> pet = getturtle()
      >>> pet.fd(50)
      >>> pet
      <turtle.Turtle object at 0x0187D810>
      >>> turtles()
      [<turtle.Turtle object at 0x0187D810>]
      """
      return self

    getpen = getturtle


    ################################################################
    ### screen oriented methods recurring to methods of TurtleScreen
    ################################################################

    def _delay(self, delay=None):
      """Set delay value which determines speed of turtle animation.
      """
      return self.screen.delay(delay)

    def onclick(self, fun, btn=1, add=None):
      self.screen._onclick(self.turtle._item, fun, btn, add)
      self._update()

    def onrelease(self, fun, btn=1, add=None):
      self.screen._onrelease(self.turtle._item, fun, btn, add)
      self._update()

    def ondrag(self, fun, btn=1, add=None):
      self.screen._ondrag(self.turtle._item, fun, btn, add)


    def _undo(self, action, data):
      """Does the main part of the work for undo()
      """
      if self.undobuffer is None:
            return
      if action == "rot":
            angle, degPAU = data
            self._rotate(-angle*degPAU/self._degreesPerAU)
            dummy = self.undobuffer.pop()
      elif action == "stamp":
            stitem = data
            self.clearstamp(stitem)
      elif action == "go":
            self._undogoto(data)
      elif action in ["wri", "dot"]:
            item = data
            self.screen._delete(item)
            self.items.remove(item)
      elif action == "dofill":
            item = data
            self.screen._drawpoly(item, ((0, 0),(0, 0),(0, 0)),
                                  fill="", outline="")
      elif action == "beginfill":
            item = data
            self._fillitem = self._fillpath = None
            if item in self.items:
                self.screen._delete(item)
                self.items.remove(item)
      elif action == "pen":
            TPen.pen(self, data)
            self.undobuffer.pop()

    def undo(self):
      if self.undobuffer is None:
            return
      item = self.undobuffer.pop()
      action = item
      data = item
      if action == "seq":
            while data:
                item = data.pop()
                self._undo(item, item)
      else:
            self._undo(action, data)

    turtlesize = shapesize

RawPen = RawTurtle

###Screen - Singleton########################

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"]

    def __init__(self):
      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:
            width = _CFG["width"]
            height = _CFG["height"]
            canvwidth = _CFG["canvwidth"]
            canvheight = _CFG["canvheight"]
            leftright = _CFG["leftright"]
            topbottom = _CFG["topbottom"]
            self._root.setupcanvas(width, height, canvwidth, canvheight)
            _Screen._canvas = self._root._getcanvas()
            TurtleScreen.__init__(self, _Screen._canvas)
            self.setup(width, height, leftright, topbottom)

    def setup(self, width=_CFG["width"], height=_CFG["height"],
            startx=_CFG["leftright"], starty=_CFG["topbottom"]):
      if not hasattr(self._root, "set_geometry"):
            return
      sw = self._root.win_width()
      sh = self._root.win_height()
      if isinstance(width, float) and 0 <= width <= 1:
            width = sw*width
      if startx is None:
            startx = (sw - width) / 2
      if isinstance(height, float) and 0 <= height <= 1:
            height = sh*height
      if starty is None:
            starty = (sh - height) / 2
      self._root.set_geometry(width, height, startx, starty)
      self.update()

    def title(self, 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:
            Turtle._pen = None
            Turtle._screen = None
            _Screen._root = None
            _Screen._canvas = None
      TurtleScreen._RUNNING = False
      root.destroy()

    def bye(self):
      """Shut the turtlegraphics window.

      Example (for a TurtleScreen instance named screen):
      >>> screen.bye()
      """
      self._destroy()

    def exitonclick(self):
      def exitGracefully(x, y):
            """Screen.bye() with two dummy-parameters"""
            self.bye()
      self.onclick(exitGracefully)
      if _CFG["using_IDLE"]:
            return
      try:
            mainloop()
      except AttributeError:
            exit(0)

class Turtle(RawTurtle):
    """RawTurtle auto-creating (scrolled) canvas.

    When a Turtle object is created or a function derived from some
    Turtle method is called a TurtleScreen object is automatically created.
    """
    _pen = None
    _screen = None

    def __init__(self,
               shape=_CFG["shape"],
               undobuffersize=_CFG["undobuffersize"],
               visible=_CFG["visible"]):
      if Turtle._screen is None:
            Turtle._screen = Screen()
      RawTurtle.__init__(self, Turtle._screen,
                           shape=shape,
                           undobuffersize=undobuffersize,
                           visible=visible)

Pen = Turtle

def write_docstringdict(filename="turtle_docstringdict"):
    docsdict = {}

    for methodname in _tg_screen_functions:
      key = "_Screen."+methodname
      docsdict = eval(key).__doc__
    for methodname in _tg_turtle_functions:
      key = "Turtle."+methodname
      docsdict = eval(key).__doc__

    with open("%s.py" % filename,"w") as f:
      keys = sorted(x for x in docsdict
                      if x.split('.') not in _alias_list)
      f.write('docsdict = {\n\n')
      for key in keys[:-1]:
            f.write('%s :\n' % repr(key))
            f.write('      """%s\n""",\n\n' % docsdict)
      key = keys[-1]
      f.write('%s :\n' % repr(key))
      f.write('      """%s\n"""\n\n' % docsdict)
      f.write("}\n")
      f.close()

def read_docstrings(lang):
    """Read in docstrings from lang-specific docstring dictionary.

    Transfer docstrings, translated to lang, from a dictionary-file
    to the methods of classes Screen and Turtle and - in revised form -
    to the corresponding functions.
    """
    modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
    module = __import__(modname)
    docsdict = module.docsdict
    for key in docsdict:
      try:
#            eval(key).im_func.__doc__ = docsdict
            eval(key).__doc__ = docsdict
      except Exception:
            print("Bad docstring-entry: %s" % key)

_LANGUAGE = _CFG["language"]

try:
    if _LANGUAGE != "english":
      read_docstrings(_LANGUAGE)
except ImportError:
    print("Cannot find docsdict for", _LANGUAGE)
except Exception:
    print ("Unknown Error when trying to import %s-docstring-dictionary" %
                                                                  _LANGUAGE)


def getmethparlist(ob):
    defText = callText = ""
    # bit of a hack for methods - turn it into a function
    # but we drop the "self" param.
    # Try and build one for Python defined functions
    args, varargs, varkw = inspect.getargs(ob.__code__)
    items2 = args
    realArgs = args
    defaults = ob.__defaults__ or []
    defaults = ["=%r" % (value,) for value in defaults]
    defaults = [""] * (len(realArgs)-len(defaults)) + defaults
    items1 =
    if varargs is not None:
      items1.append("*" + varargs)
      items2.append("*" + varargs)
    if varkw is not None:
      items1.append("**" + varkw)
      items2.append("**" + varkw)
    defText = ", ".join(items1)
    defText = "(%s)" % defText
    callText = ", ".join(items2)
    callText = "(%s)" % callText
    return defText, callText

def _turtle_docrevise(docstr):
    """To reduce docstrings from RawTurtle class for functions
    """
    import re
    if docstr is None:
      return None
    turtlename = _CFG["exampleturtle"]
    newdocstr = docstr.replace("%s." % turtlename,"")
    parexp = re.compile(r' \(.+ %s\):' % turtlename)
    newdocstr = parexp.sub(":", newdocstr)
    return newdocstr

def _screen_docrevise(docstr):
    """To reduce docstrings from TurtleScreen class for functions
    """
    import re
    if docstr is None:
      return None
    screenname = _CFG["examplescreen"]
    newdocstr = docstr.replace("%s." % screenname,"")
    parexp = re.compile(r' \(.+ %s\):' % screenname)
    newdocstr = parexp.sub(":", newdocstr)
    return newdocstr

## The following mechanism makes all methods of RawTurtle and Turtle available
## as functions. So we can enhance, change, add, delete methods to these
## classes and do not need to change anything here.

__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, globals())
      globals().__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

if __name__ == "__main__":
    def switchpen():
      if isdown():
            pu()
      else:
            pd()

    def demo1():
      """Demo of old turtle.py - module"""
      reset()
      tracer(True)
      up()
      backward(100)
      down()
      # draw 3 squares; the last filled
      width(3)
      for i in range(3):
            if i == 2:
                begin_fill()
            for _ in range(4):
                forward(20)
                left(90)
            if i == 2:
                color("maroon")
                end_fill()
            up()
            forward(30)
            down()
      width(1)
      color("black")
      # move out of the way
      tracer(False)
      up()
      right(90)
      forward(100)
      right(90)
      forward(100)
      right(180)
      down()
      # some text
      write("startstart", 1)
      write("start", 1)
      color("red")
      # staircase
      for i in range(5):
            forward(20)
            left(90)
            forward(20)
            right(90)
      # filled staircase
      tracer(True)
      begin_fill()
      for i in range(5):
            forward(20)
            left(90)
            forward(20)
            right(90)
      end_fill()
      # more text

    def demo2():
      """Demo of some new features."""
      speed(1)
      st()
      pensize(3)
      setheading(towards(0, 0))
      radius = distance(0, 0)/2.0
      rt(90)
      for _ in range(18):
            switchpen()
            circle(radius, 10)
      write("wait a moment...")
      while undobufferentries():
            undo()
      reset()
      lt(90)
      colormode(255)
      laenge = 10
      pencolor("green")
      pensize(3)
      lt(180)
      for i in range(-2, 16):
            if i > 0:
                begin_fill()
                fillcolor(255-15*i, 0, 15*i)
            for _ in range(3):
                fd(laenge)
                lt(120)
            end_fill()
            laenge += 10
            lt(15)
            speed((speed()+1)%12)
      #end_fill()

      lt(120)
      pu()
      fd(70)
      rt(30)
      pd()
      color("red","yellow")
      speed(0)
      begin_fill()
      for _ in range(4):
            circle(50, 90)
            rt(90)
            fd(30)
            rt(90)
      end_fill()
      lt(90)
      pu()
      fd(30)
      pd()
      shape("turtle")

      tri = getturtle()
      tri.resizemode("auto")
      turtle = Turtle()
      turtle.resizemode("auto")
      turtle.shape("turtle")
      turtle.reset()
      turtle.left(90)
      turtle.speed(0)
      turtle.up()
      turtle.goto(280, 40)
      turtle.lt(30)
      turtle.down()
      turtle.speed(6)
      turtle.color("blue","orange")
      turtle.pensize(2)
      tri.speed(6)
      setheading(towards(turtle))
      count = 1
      while tri.distance(turtle) > 4:
            turtle.fd(3.5)
            turtle.lt(0.6)
            tri.setheading(tri.towards(turtle))
            tri.fd(4)
            if count % 20 == 0:
                turtle.stamp()
                tri.stamp()
                switchpen()
            count += 1
      tri.write("CAUGHT! ", font=("Arial", 16, "bold"), align="right")
      tri.pencolor("black")
      tri.pencolor("red")

      def baba(xdummy, ydummy):
            clearscreen()
            bye()

      time.sleep(2)

      while undobufferentries():
            tri.undo()
            turtle.undo()
      tri.fd(50)
      tri.write("Click me!", font = ("Courier", 12, "bold") )
      tri.onclick(baba, 1)

    demo1()
    demo2()
    exitonclick()最后保存应该就没问题了。(网站对帖子字数有限制,因此代码中省略了部分注释和文档,但不影响功能使用)

如果还是不行建议重装Python

hrp 发表于 2021-2-19 15:01:07

安装新版本Python,建议3.8

xsywa 发表于 2021-2-20 09:33:23

考不好不改名 发表于 2021-2-19 14:08
你找到你Python安装的目录(默认是C:%users\33260\AppData\Local\Programs\Python);在目录下打开Lib,看 ...

加了turtle.py,还是不行,出现了新的问题,我准备安装3.8了,就是有点疑惑,后面出现的这个是为啥呢

xsywa 发表于 2021-2-20 09:35:06

考不好不改名 发表于 2021-2-19 14:03
建议重装Python

准备重装了
页: [1]
查看完整版本: turtle