import sys from _typeshed import StrPath from collections.abc import Callable, Generator, Sequence from contextlib import contextmanager from tkinter import Canvas, Frame, Misc, PhotoImage, Scrollbar from typing import Any, ClassVar, Literal, TypedDict, overload from typing_extensions import Self, TypeAlias __all__ = [ "ScrolledCanvas", "TurtleScreen", "Screen", "RawTurtle", "Turtle", "RawPen", "Pen", "Shape", "Vec2D", "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", "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", "setundobuffer", "setx", "sety", "shape", "shapesize", "shapetransform", "shearfactor", "showturtle", "speed", "st", "stamp", "tilt", "tiltangle", "towards", "turtlesize", "undo", "undobufferentries", "up", "width", "write", "xcor", "ycor", "write_docstringdict", "done", "Terminator", ] if sys.version_info >= (3, 14): __all__ += ["fill", "no_animation", "poly", "save"] if sys.version_info >= (3, 12): __all__ += ["teleport"] if sys.version_info < (3, 13): __all__ += ["settiltangle"] # Note: '_Color' is the alias we use for arguments and _AnyColor is the # alias we use for return types. Really, these two aliases should be the # same, but as per the "no union returns" typeshed policy, we'll return # Any instead. _Color: TypeAlias = str | tuple[float, float, float] _AnyColor: TypeAlias = Any class _PenState(TypedDict): shown: bool pendown: bool pencolor: _Color fillcolor: _Color pensize: int speed: int resizemode: Literal["auto", "user", "noresize"] stretchfactor: tuple[float, float] shearfactor: float outline: int tilt: float _Speed: TypeAlias = str | float _PolygonCoords: TypeAlias = Sequence[tuple[float, float]] class Vec2D(tuple[float, float]): def __new__(cls, x: float, y: float) -> Self: ... def __add__(self, other: tuple[float, float]) -> Vec2D: ... # type: ignore[override] @overload # type: ignore[override] def __mul__(self, other: Vec2D) -> float: ... @overload def __mul__(self, other: float) -> Vec2D: ... def __rmul__(self, other: float) -> Vec2D: ... # type: ignore[override] def __sub__(self, other: tuple[float, float]) -> Vec2D: ... def __neg__(self) -> Vec2D: ... def __abs__(self) -> float: ... def rotate(self, angle: float) -> Vec2D: ... # Does not actually inherit from Canvas, but dynamically gets all methods of Canvas class ScrolledCanvas(Canvas, Frame): # type: ignore[misc] bg: str hscroll: Scrollbar vscroll: Scrollbar def __init__( self, master: Misc | None, width: int = 500, height: int = 350, canvwidth: int = 600, canvheight: int = 500 ) -> None: ... canvwidth: int canvheight: int def reset(self, canvwidth: int | None = None, canvheight: int | None = None, bg: str | None = None) -> None: ... class TurtleScreenBase: cv: Canvas canvwidth: int canvheight: int xscale: float yscale: float def __init__(self, cv: Canvas) -> None: ... def mainloop(self) -> None: ... def textinput(self, title: str, prompt: str) -> str | None: ... def numinput( self, title: str, prompt: str, default: float | None = None, minval: float | None = None, maxval: float | None = None ) -> float | None: ... class Terminator(Exception): ... class TurtleGraphicsError(Exception): ... class Shape: def __init__(self, type_: str, data: _PolygonCoords | PhotoImage | None = None) -> None: ... def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: _Color | None = None) -> None: ... class TurtleScreen(TurtleScreenBase): def __init__(self, cv: Canvas, mode: str = "standard", colormode: float = 1.0, delay: int = 10) -> None: ... def clear(self) -> None: ... @overload def mode(self, mode: None = None) -> str: ... @overload def mode(self, mode: str) -> None: ... def setworldcoordinates(self, llx: float, lly: float, urx: float, ury: float) -> None: ... def register_shape(self, name: str, shape: _PolygonCoords | Shape | None = None) -> None: ... @overload def colormode(self, cmode: None = None) -> float: ... @overload def colormode(self, cmode: float) -> None: ... def reset(self) -> None: ... def turtles(self) -> list[Turtle]: ... @overload def bgcolor(self) -> _AnyColor: ... @overload def bgcolor(self, color: _Color) -> None: ... @overload def bgcolor(self, r: float, g: float, b: float) -> None: ... @overload def tracer(self, n: None = None) -> int: ... @overload def tracer(self, n: int, delay: int | None = None) -> None: ... @overload def delay(self, delay: None = None) -> int: ... @overload def delay(self, delay: int) -> None: ... if sys.version_info >= (3, 14): @contextmanager def no_animation(self) -> Generator[None]: ... def update(self) -> None: ... def window_width(self) -> int: ... def window_height(self) -> int: ... def getcanvas(self) -> Canvas: ... def getshapes(self) -> list[str]: ... def onclick(self, fun: Callable[[float, float], object], btn: int = 1, add: Any | None = None) -> None: ... def onkey(self, fun: Callable[[], object], key: str) -> None: ... def listen(self, xdummy: float | None = None, ydummy: float | None = None) -> None: ... def ontimer(self, fun: Callable[[], object], t: int = 0) -> None: ... @overload def bgpic(self, picname: None = None) -> str: ... @overload def bgpic(self, picname: str) -> None: ... @overload def screensize(self, canvwidth: None = None, canvheight: None = None, bg: None = None) -> tuple[int, int]: ... # Looks like if self.cv is not a ScrolledCanvas, this could return a tuple as well @overload def screensize(self, canvwidth: int, canvheight: int, bg: _Color | None = None) -> None: ... if sys.version_info >= (3, 14): def save(self, filename: StrPath, *, overwrite: bool = False) -> None: ... onscreenclick = onclick resetscreen = reset clearscreen = clear addshape = register_shape def onkeypress(self, fun: Callable[[], object], key: str | None = None) -> None: ... onkeyrelease = onkey class TNavigator: START_ORIENTATION: dict[str, Vec2D] DEFAULT_MODE: str DEFAULT_ANGLEOFFSET: int DEFAULT_ANGLEORIENT: int def __init__(self, mode: str = "standard") -> None: ... def reset(self) -> None: ... def degrees(self, fullcircle: float = 360.0) -> None: ... def radians(self) -> None: ... if sys.version_info >= (3, 12): def teleport(self, x: float | None = None, y: float | None = None, *, fill_gap: bool = False) -> None: ... def forward(self, distance: float) -> None: ... def back(self, distance: float) -> None: ... def right(self, angle: float) -> None: ... def left(self, angle: float) -> None: ... def pos(self) -> Vec2D: ... def xcor(self) -> float: ... def ycor(self) -> float: ... @overload def goto(self, x: tuple[float, float], y: None = None) -> None: ... @overload def goto(self, x: float, y: float) -> None: ... def home(self) -> None: ... def setx(self, x: float) -> None: ... def sety(self, y: float) -> None: ... @overload def distance(self, x: TNavigator | tuple[float, float], y: None = None) -> float: ... @overload def distance(self, x: float, y: float) -> float: ... @overload def towards(self, x: TNavigator | tuple[float, float], y: None = None) -> float: ... @overload def towards(self, x: float, y: float) -> float: ... def heading(self) -> float: ... def setheading(self, to_angle: float) -> None: ... def circle(self, radius: float, extent: float | None = None, steps: int | None = None) -> None: ... def speed(self, s: int | None = 0) -> int | None: ... fd = forward bk = back backward = back rt = right lt = left position = pos setpos = goto setposition = goto seth = setheading class TPen: def __init__(self, resizemode: str = "noresize") -> None: ... @overload def resizemode(self, rmode: None = None) -> str: ... @overload def resizemode(self, rmode: str) -> None: ... @overload def pensize(self, width: None = None) -> int: ... @overload def pensize(self, width: int) -> None: ... def penup(self) -> None: ... def pendown(self) -> None: ... def isdown(self) -> bool: ... @overload def speed(self, speed: None = None) -> int: ... @overload def speed(self, speed: _Speed) -> None: ... @overload def pencolor(self) -> _AnyColor: ... @overload def pencolor(self, color: _Color) -> None: ... @overload def pencolor(self, r: float, g: float, b: float) -> None: ... @overload def fillcolor(self) -> _AnyColor: ... @overload def fillcolor(self, color: _Color) -> None: ... @overload def fillcolor(self, r: float, g: float, b: float) -> None: ... @overload def color(self) -> tuple[_AnyColor, _AnyColor]: ... @overload def color(self, color: _Color) -> None: ... @overload def color(self, r: float, g: float, b: float) -> None: ... @overload def color(self, color1: _Color, color2: _Color) -> None: ... if sys.version_info >= (3, 12): def teleport(self, x: float | None = None, y: float | None = None, *, fill_gap: bool = False) -> None: ... def showturtle(self) -> None: ... def hideturtle(self) -> None: ... def isvisible(self) -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload def pen(self) -> _PenState: ... @overload def pen( self, pen: _PenState | None = None, *, shown: bool = ..., pendown: bool = ..., pencolor: _Color = ..., fillcolor: _Color = ..., pensize: int = ..., speed: int = ..., resizemode: str = ..., stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... width = pensize up = penup pu = penup pd = pendown down = pendown st = showturtle ht = hideturtle class RawTurtle(TPen, TNavigator): # type: ignore[misc] # Conflicting methods in base classes screen: TurtleScreen screens: ClassVar[list[TurtleScreen]] def __init__( self, canvas: Canvas | TurtleScreen | None = None, shape: str = "classic", undobuffersize: int = 1000, visible: bool = True, ) -> None: ... def reset(self) -> None: ... def setundobuffer(self, size: int | None) -> None: ... def undobufferentries(self) -> int: ... def clear(self) -> None: ... def clone(self) -> Self: ... @overload def shape(self, name: None = None) -> str: ... @overload def shape(self, name: str) -> None: ... # Unsafely overlaps when no arguments are provided @overload def shapesize(self) -> tuple[float, float, float]: ... @overload def shapesize( self, stretch_wid: float | None = None, stretch_len: float | None = None, outline: float | None = None ) -> None: ... @overload def shearfactor(self, shear: None = None) -> float: ... @overload def shearfactor(self, shear: float) -> None: ... # Unsafely overlaps when no arguments are provided @overload def shapetransform(self) -> tuple[float, float, float, float]: ... @overload def shapetransform( self, t11: float | None = None, t12: float | None = None, t21: float | None = None, t22: float | None = None ) -> None: ... def get_shapepoly(self) -> _PolygonCoords | None: ... if sys.version_info < (3, 13): def settiltangle(self, angle: float) -> None: ... @overload def tiltangle(self, angle: None = None) -> float: ... @overload def tiltangle(self, angle: float) -> None: ... def tilt(self, angle: float) -> None: ... # Can return either 'int' or Tuple[int, ...] based on if the stamp is # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp(self) -> Any: ... def clearstamp(self, stampid: int | tuple[int, ...]) -> None: ... def clearstamps(self, n: int | None = None) -> None: ... def filling(self) -> bool: ... if sys.version_info >= (3, 14): @contextmanager def fill(self) -> Generator[None]: ... def begin_fill(self) -> None: ... def end_fill(self) -> None: ... def dot(self, size: int | None = None, *color: _Color) -> None: ... def write( self, arg: object, move: bool = False, align: str = "left", font: tuple[str, int, str] = ("Arial", 8, "normal") ) -> None: ... if sys.version_info >= (3, 14): @contextmanager def poly(self) -> Generator[None]: ... def begin_poly(self) -> None: ... def end_poly(self) -> None: ... def get_poly(self) -> _PolygonCoords | None: ... def getscreen(self) -> TurtleScreen: ... def getturtle(self) -> Self: ... getpen = getturtle def onclick(self, fun: Callable[[float, float], object], btn: int = 1, add: bool | None = None) -> None: ... def onrelease(self, fun: Callable[[float, float], object], btn: int = 1, add: bool | None = None) -> None: ... def ondrag(self, fun: Callable[[float, float], object], btn: int = 1, add: bool | None = None) -> None: ... def undo(self) -> None: ... turtlesize = shapesize class _Screen(TurtleScreen): def __init__(self) -> None: ... # Note int and float are interpreted differently, hence the Union instead of just float def setup( self, width: int | float = 0.5, # noqa: Y041 height: int | float = 0.75, # noqa: Y041 startx: int | None = None, starty: int | None = None, ) -> None: ... def title(self, titlestring: str) -> None: ... def bye(self) -> None: ... def exitonclick(self) -> None: ... class Turtle(RawTurtle): def __init__(self, shape: str = "classic", undobuffersize: int = 1000, visible: bool = True) -> None: ... RawPen = RawTurtle Pen = Turtle def write_docstringdict(filename: str = "turtle_docstringdict") -> None: ... # Note: it's somewhat unfortunate that we have to copy the function signatures. # It would be nice if we could partially reduce the redundancy by doing something # like the following: # # _screen: Screen # clear = _screen.clear # # However, it seems pytype does not support this type of syntax in pyi files. # Functions copied from TurtleScreenBase: # Note: mainloop() was always present in the global scope, but was added to # TurtleScreenBase in Python 3.0 def mainloop() -> None: ... def textinput(title: str, prompt: str) -> str | None: ... def numinput( title: str, prompt: str, default: float | None = None, minval: float | None = None, maxval: float | None = None ) -> float | None: ... # Functions copied from TurtleScreen: def clear() -> None: ... @overload def mode(mode: None = None) -> str: ... @overload def mode(mode: str) -> None: ... def setworldcoordinates(llx: float, lly: float, urx: float, ury: float) -> None: ... def register_shape(name: str, shape: _PolygonCoords | Shape | None = None) -> None: ... @overload def colormode(cmode: None = None) -> float: ... @overload def colormode(cmode: float) -> None: ... def reset() -> None: ... def turtles() -> list[Turtle]: ... @overload def bgcolor() -> _AnyColor: ... @overload def bgcolor(color: _Color) -> None: ... @overload def bgcolor(r: float, g: float, b: float) -> None: ... @overload def tracer(n: None = None) -> int: ... @overload def tracer(n: int, delay: int | None = None) -> None: ... @overload def delay(delay: None = None) -> int: ... @overload def delay(delay: int) -> None: ... if sys.version_info >= (3, 14): @contextmanager def no_animation() -> Generator[None]: ... def update() -> None: ... def window_width() -> int: ... def window_height() -> int: ... def getcanvas() -> Canvas: ... def getshapes() -> list[str]: ... def onclick(fun: Callable[[float, float], object], btn: int = 1, add: Any | None = None) -> None: ... def onkey(fun: Callable[[], object], key: str) -> None: ... def listen(xdummy: float | None = None, ydummy: float | None = None) -> None: ... def ontimer(fun: Callable[[], object], t: int = 0) -> None: ... @overload def bgpic(picname: None = None) -> str: ... @overload def bgpic(picname: str) -> None: ... @overload def screensize(canvwidth: None = None, canvheight: None = None, bg: None = None) -> tuple[int, int]: ... @overload def screensize(canvwidth: int, canvheight: int, bg: _Color | None = None) -> None: ... if sys.version_info >= (3, 14): def save(filename: StrPath, *, overwrite: bool = False) -> None: ... onscreenclick = onclick resetscreen = reset clearscreen = clear addshape = register_shape def onkeypress(fun: Callable[[], object], key: str | None = None) -> None: ... onkeyrelease = onkey # Functions copied from _Screen: def setup(width: float = 0.5, height: float = 0.75, startx: int | None = None, starty: int | None = None) -> None: ... def title(titlestring: str) -> None: ... def bye() -> None: ... def exitonclick() -> None: ... def Screen() -> _Screen: ... # Functions copied from TNavigator: def degrees(fullcircle: float = 360.0) -> None: ... def radians() -> None: ... def forward(distance: float) -> None: ... def back(distance: float) -> None: ... def right(angle: float) -> None: ... def left(angle: float) -> None: ... def pos() -> Vec2D: ... def xcor() -> float: ... def ycor() -> float: ... @overload def goto(x: tuple[float, float], y: None = None) -> None: ... @overload def goto(x: float, y: float) -> None: ... def home() -> None: ... def setx(x: float) -> None: ... def sety(y: float) -> None: ... @overload def distance(x: TNavigator | tuple[float, float], y: None = None) -> float: ... @overload def distance(x: float, y: float) -> float: ... @overload def towards(x: TNavigator | tuple[float, float], y: None = None) -> float: ... @overload def towards(x: float, y: float) -> float: ... def heading() -> float: ... def setheading(to_angle: float) -> None: ... def circle(radius: float, extent: float | None = None, steps: int | None = None) -> None: ... fd = forward bk = back backward = back rt = right lt = left position = pos setpos = goto setposition = goto seth = setheading # Functions copied from TPen: @overload def resizemode(rmode: None = None) -> str: ... @overload def resizemode(rmode: str) -> None: ... @overload def pensize(width: None = None) -> int: ... @overload def pensize(width: int) -> None: ... def penup() -> None: ... def pendown() -> None: ... def isdown() -> bool: ... @overload def speed(speed: None = None) -> int: ... @overload def speed(speed: _Speed) -> None: ... @overload def pencolor() -> _AnyColor: ... @overload def pencolor(color: _Color) -> None: ... @overload def pencolor(r: float, g: float, b: float) -> None: ... @overload def fillcolor() -> _AnyColor: ... @overload def fillcolor(color: _Color) -> None: ... @overload def fillcolor(r: float, g: float, b: float) -> None: ... @overload def color() -> tuple[_AnyColor, _AnyColor]: ... @overload def color(color: _Color) -> None: ... @overload def color(r: float, g: float, b: float) -> None: ... @overload def color(color1: _Color, color2: _Color) -> None: ... def showturtle() -> None: ... def hideturtle() -> None: ... def isvisible() -> bool: ... # Note: signatures 1 and 2 overlap unsafely when no arguments are provided @overload def pen() -> _PenState: ... @overload def pen( pen: _PenState | None = None, *, shown: bool = ..., pendown: bool = ..., pencolor: _Color = ..., fillcolor: _Color = ..., pensize: int = ..., speed: int = ..., resizemode: str = ..., stretchfactor: tuple[float, float] = ..., outline: int = ..., tilt: float = ..., ) -> None: ... width = pensize up = penup pu = penup pd = pendown down = pendown st = showturtle ht = hideturtle # Functions copied from RawTurtle: def setundobuffer(size: int | None) -> None: ... def undobufferentries() -> int: ... @overload def shape(name: None = None) -> str: ... @overload def shape(name: str) -> None: ... if sys.version_info >= (3, 12): def teleport(x: float | None = None, y: float | None = None, *, fill_gap: bool = False) -> None: ... # Unsafely overlaps when no arguments are provided @overload def shapesize() -> tuple[float, float, float]: ... @overload def shapesize(stretch_wid: float | None = None, stretch_len: float | None = None, outline: float | None = None) -> None: ... @overload def shearfactor(shear: None = None) -> float: ... @overload def shearfactor(shear: float) -> None: ... # Unsafely overlaps when no arguments are provided @overload def shapetransform() -> tuple[float, float, float, float]: ... @overload def shapetransform( t11: float | None = None, t12: float | None = None, t21: float | None = None, t22: float | None = None ) -> None: ... def get_shapepoly() -> _PolygonCoords | None: ... if sys.version_info < (3, 13): def settiltangle(angle: float) -> None: ... @overload def tiltangle(angle: None = None) -> float: ... @overload def tiltangle(angle: float) -> None: ... def tilt(angle: float) -> None: ... # Can return either 'int' or Tuple[int, ...] based on if the stamp is # a compound stamp or not. So, as per the "no Union return" policy, # we return Any. def stamp() -> Any: ... def clearstamp(stampid: int | tuple[int, ...]) -> None: ... def clearstamps(n: int | None = None) -> None: ... def filling() -> bool: ... if sys.version_info >= (3, 14): @contextmanager def fill() -> Generator[None]: ... def begin_fill() -> None: ... def end_fill() -> None: ... def dot(size: int | None = None, *color: _Color) -> None: ... def write(arg: object, move: bool = False, align: str = "left", font: tuple[str, int, str] = ("Arial", 8, "normal")) -> None: ... if sys.version_info >= (3, 14): @contextmanager def poly() -> Generator[None]: ... def begin_poly() -> None: ... def end_poly() -> None: ... def get_poly() -> _PolygonCoords | None: ... def getscreen() -> TurtleScreen: ... def getturtle() -> Turtle: ... getpen = getturtle def onrelease(fun: Callable[[float, float], object], btn: int = 1, add: Any | None = None) -> None: ... def ondrag(fun: Callable[[float, float], object], btn: int = 1, add: Any | None = None) -> None: ... def undo() -> None: ... turtlesize = shapesize # Functions copied from RawTurtle with a few tweaks: def clone() -> Turtle: ... # Extra functions present only in the global scope: done = mainloop