1import sys
2from typing import Any, Callable, Dict, List, Optional, Sequence, Text, Tuple, TypeVar, Union, overload
3
4if sys.version_info >= (3,):
5    from tkinter import Canvas, PhotoImage
6else:
7    # TODO: Replace these aliases once we have Python 2 stubs for the Tkinter module.
8    Canvas = Any
9    PhotoImage = Any
10
11# Note: '_Color' is the alias we use for arguments and _AnyColor is the
12# alias we use for return types. Really, these two aliases should be the
13# same, but as per the "no union returns" typeshed policy, we'll return
14# Any instead.
15_Color = Union[Text, Tuple[float, float, float]]
16_AnyColor = Any
17
18# TODO: Replace this with a TypedDict once it becomes standardized.
19_PenState = Dict[str, Any]
20
21_Speed = Union[str, float]
22_PolygonCoords = Sequence[Tuple[float, float]]
23
24# TODO: Type this more accurately
25# Vec2D is actually a custom subclass of 'tuple'.
26Vec2D = Tuple[float, float]
27
28class TurtleScreenBase(object):
29    cv: Canvas = ...
30    canvwidth: int = ...
31    canvheight: int = ...
32    xscale: float = ...
33    yscale: float = ...
34    def __init__(self, cv: Canvas) -> None: ...
35    if sys.version_info >= (3,):
36        def mainloop(self) -> None: ...
37        def textinput(self, title: str, prompt: str) -> Optional[str]: ...
38        def numinput(
39            self,
40            title: str,
41            prompt: str,
42            default: Optional[float] = ...,
43            minval: Optional[float] = ...,
44            maxval: Optional[float] = ...,
45        ) -> Optional[float]: ...
46
47class Terminator(Exception): ...
48class TurtleGraphicsError(Exception): ...
49
50class Shape(object):
51    def __init__(self, type_: str, data: Union[_PolygonCoords, PhotoImage, None] = ...) -> None: ...
52    def addcomponent(self, poly: _PolygonCoords, fill: _Color, outline: Optional[_Color] = ...) -> None: ...
53
54class TurtleScreen(TurtleScreenBase):
55    def __init__(self, cv: Canvas, mode: str = ..., colormode: float = ..., delay: int = ...) -> None: ...
56    def clear(self) -> None: ...
57    @overload
58    def mode(self, mode: None = ...) -> str: ...
59    @overload
60    def mode(self, mode: str) -> None: ...
61    def setworldcoordinates(self, llx: float, lly: float, urx: float, ury: float) -> None: ...
62    def register_shape(self, name: str, shape: Union[_PolygonCoords, Shape, None] = ...) -> None: ...
63    @overload
64    def colormode(self, cmode: None = ...) -> float: ...
65    @overload
66    def colormode(self, cmode: float) -> None: ...
67    def reset(self) -> None: ...
68    def turtles(self) -> List[Turtle]: ...
69    @overload
70    def bgcolor(self) -> _AnyColor: ...
71    @overload
72    def bgcolor(self, color: _Color) -> None: ...
73    @overload
74    def bgcolor(self, r: float, g: float, b: float) -> None: ...
75    @overload
76    def tracer(self, n: None = ...) -> int: ...
77    @overload
78    def tracer(self, n: int, delay: Optional[int] = ...) -> None: ...
79    @overload
80    def delay(self, delay: None = ...) -> int: ...
81    @overload
82    def delay(self, delay: int) -> None: ...
83    def update(self) -> None: ...
84    def window_width(self) -> int: ...
85    def window_height(self) -> int: ...
86    def getcanvas(self) -> Canvas: ...
87    def getshapes(self) -> List[str]: ...
88    def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ...
89    def onkey(self, fun: Callable[[], Any], key: str) -> None: ...
90    def listen(self, xdummy: Optional[float] = ..., ydummy: Optional[float] = ...) -> None: ...
91    def ontimer(self, fun: Callable[[], Any], t: int = ...) -> None: ...
92    @overload
93    def bgpic(self, picname: None = ...) -> str: ...
94    @overload
95    def bgpic(self, picname: str) -> None: ...
96    @overload
97    def screensize(self, canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ...
98    # Looks like if self.cv is not a ScrolledCanvas, this could return a tuple as well
99    @overload
100    def screensize(self, canvwidth: int, canvheight: int, bg: Optional[_Color] = ...) -> None: ...
101    onscreenclick = onclick
102    resetscreen = reset
103    clearscreen = clear
104    addshape = register_shape
105    if sys.version_info >= (3,):
106        def onkeypress(self, fun: Callable[[], Any], key: Optional[str] = ...) -> None: ...
107        onkeyrelease = onkey
108
109class TNavigator(object):
110    START_ORIENTATION: Dict[str, Vec2D] = ...
111    DEFAULT_MODE: str = ...
112    DEFAULT_ANGLEOFFSET: int = ...
113    DEFAULT_ANGLEORIENT: int = ...
114    def __init__(self, mode: str = ...) -> None: ...
115    def reset(self) -> None: ...
116    def degrees(self, fullcircle: float = ...) -> None: ...
117    def radians(self) -> None: ...
118    def forward(self, distance: float) -> None: ...
119    def back(self, distance: float) -> None: ...
120    def right(self, angle: float) -> None: ...
121    def left(self, angle: float) -> None: ...
122    def pos(self) -> Vec2D: ...
123    def xcor(self) -> float: ...
124    def ycor(self) -> float: ...
125    @overload
126    def goto(self, x: Tuple[float, float], y: None = ...) -> None: ...
127    @overload
128    def goto(self, x: float, y: float) -> None: ...
129    def home(self) -> None: ...
130    def setx(self, x: float) -> None: ...
131    def sety(self, y: float) -> None: ...
132    @overload
133    def distance(self, x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ...
134    @overload
135    def distance(self, x: float, y: float) -> float: ...
136    @overload
137    def towards(self, x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ...
138    @overload
139    def towards(self, x: float, y: float) -> float: ...
140    def heading(self) -> float: ...
141    def setheading(self, to_angle: float) -> None: ...
142    def circle(self, radius: float, extent: Optional[float] = ..., steps: Optional[int] = ...) -> None: ...
143    fd = forward
144    bk = back
145    backward = back
146    rt = right
147    lt = left
148    position = pos
149    setpos = goto
150    setposition = goto
151    seth = setheading
152
153class TPen(object):
154    def __init__(self, resizemode: str = ...) -> None: ...
155    @overload
156    def resizemode(self, rmode: None = ...) -> str: ...
157    @overload
158    def resizemode(self, rmode: str) -> None: ...
159    @overload
160    def pensize(self, width: None = ...) -> int: ...
161    @overload
162    def pensize(self, width: int) -> None: ...
163    def penup(self) -> None: ...
164    def pendown(self) -> None: ...
165    def isdown(self) -> bool: ...
166    @overload
167    def speed(self, speed: None = ...) -> int: ...
168    @overload
169    def speed(self, speed: _Speed) -> None: ...
170    @overload
171    def pencolor(self) -> _AnyColor: ...
172    @overload
173    def pencolor(self, color: _Color) -> None: ...
174    @overload
175    def pencolor(self, r: float, g: float, b: float) -> None: ...
176    @overload
177    def fillcolor(self) -> _AnyColor: ...
178    @overload
179    def fillcolor(self, color: _Color) -> None: ...
180    @overload
181    def fillcolor(self, r: float, g: float, b: float) -> None: ...
182    @overload
183    def color(self) -> Tuple[_AnyColor, _AnyColor]: ...
184    @overload
185    def color(self, color: _Color) -> None: ...
186    @overload
187    def color(self, r: float, g: float, b: float) -> None: ...
188    @overload
189    def color(self, color1: _Color, color2: _Color) -> None: ...
190    def showturtle(self) -> None: ...
191    def hideturtle(self) -> None: ...
192    def isvisible(self) -> bool: ...
193    # Note: signatures 1 and 2 overlap unsafely when no arguments are provided
194    @overload
195    def pen(self) -> _PenState: ...  # type: ignore
196    @overload
197    def pen(
198        self,
199        pen: Optional[_PenState] = ...,
200        *,
201        shown: bool = ...,
202        pendown: bool = ...,
203        pencolor: _Color = ...,
204        fillcolor: _Color = ...,
205        pensize: int = ...,
206        speed: int = ...,
207        resizemode: str = ...,
208        stretchfactor: Tuple[float, float] = ...,
209        outline: int = ...,
210        tilt: float = ...,
211    ) -> None: ...
212    width = pensize
213    up = penup
214    pu = penup
215    pd = pendown
216    down = pendown
217    st = showturtle
218    ht = hideturtle
219
220_T = TypeVar("_T")
221
222class RawTurtle(TPen, TNavigator):
223    def __init__(
224        self, canvas: Union[Canvas, TurtleScreen, None] = ..., shape: str = ..., undobuffersize: int = ..., visible: bool = ...
225    ) -> None: ...
226    def reset(self) -> None: ...
227    def setundobuffer(self, size: Optional[int]) -> None: ...
228    def undobufferentries(self) -> int: ...
229    def clear(self) -> None: ...
230    def clone(self: _T) -> _T: ...
231    @overload
232    def shape(self, name: None = ...) -> str: ...
233    @overload
234    def shape(self, name: str) -> None: ...
235    # Unsafely overlaps when no arguments are provided
236    @overload
237    def shapesize(self) -> Tuple[float, float, float]: ...  # type: ignore
238    @overload
239    def shapesize(
240        self, stretch_wid: Optional[float] = ..., stretch_len: Optional[float] = ..., outline: Optional[float] = ...
241    ) -> None: ...
242    if sys.version_info >= (3,):
243        @overload
244        def shearfactor(self, shear: None = ...) -> float: ...
245        @overload
246        def shearfactor(self, shear: float) -> None: ...
247        # Unsafely overlaps when no arguments are provided
248        @overload
249        def shapetransform(self) -> Tuple[float, float, float, float]: ...  # type: ignore
250        @overload
251        def shapetransform(
252            self, t11: Optional[float] = ..., t12: Optional[float] = ..., t21: Optional[float] = ..., t22: Optional[float] = ...
253        ) -> None: ...
254        def get_shapepoly(self) -> Optional[_PolygonCoords]: ...
255    def settiltangle(self, angle: float) -> None: ...
256    @overload
257    def tiltangle(self, angle: None = ...) -> float: ...
258    @overload
259    def tiltangle(self, angle: float) -> None: ...
260    def tilt(self, angle: float) -> None: ...
261    # Can return either 'int' or Tuple[int, ...] based on if the stamp is
262    # a compound stamp or not. So, as per the "no Union return" policy,
263    # we return Any.
264    def stamp(self) -> Any: ...
265    def clearstamp(self, stampid: Union[int, Tuple[int, ...]]) -> None: ...
266    def clearstamps(self, n: Optional[int] = ...) -> None: ...
267    def filling(self) -> bool: ...
268    def begin_fill(self) -> None: ...
269    def end_fill(self) -> None: ...
270    def dot(self, size: Optional[int] = ..., *color: _Color) -> None: ...
271    def write(self, arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ...
272    def begin_poly(self) -> None: ...
273    def end_poly(self) -> None: ...
274    def get_poly(self) -> Optional[_PolygonCoords]: ...
275    def getscreen(self) -> TurtleScreen: ...
276    def getturtle(self: _T) -> _T: ...
277    getpen = getturtle
278    def onclick(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ...
279    def onrelease(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ...
280    def ondrag(self, fun: Callable[[float, float], Any], btn: int = ..., add: Optional[bool] = ...) -> None: ...
281    def undo(self) -> None: ...
282    turtlesize = shapesize
283
284class _Screen(TurtleScreen):
285    def __init__(self) -> None: ...
286    # Note int and float are interpreted differently, hence the Union instead of just float
287    def setup(
288        self,
289        width: Union[int, float] = ...,
290        height: Union[int, float] = ...,
291        startx: Optional[int] = ...,
292        starty: Optional[int] = ...,
293    ) -> None: ...
294    def title(self, titlestring: str) -> None: ...
295    def bye(self) -> None: ...
296    def exitonclick(self) -> None: ...
297
298class Turtle(RawTurtle):
299    def __init__(self, shape: str = ..., undobuffersize: int = ..., visible: bool = ...) -> None: ...
300
301RawPen = RawTurtle
302Pen = Turtle
303
304def write_docstringdict(filename: str = ...) -> None: ...
305
306# Note: it's somewhat unfortunate that we have to copy the function signatures.
307# It would be nice if we could partially reduce the redundancy by doing something
308# like the following:
309#
310#     _screen: Screen
311#     clear = _screen.clear
312#
313# However, it seems pytype does not support this type of syntax in pyi files.
314
315# Functions copied from TurtleScreenBase:
316
317# Note: mainloop() was always present in the global scope, but was added to
318# TurtleScreenBase in Python 3.0
319def mainloop() -> None: ...
320
321if sys.version_info >= (3,):
322    def textinput(title: str, prompt: str) -> Optional[str]: ...
323    def numinput(
324        title: str, prompt: str, default: Optional[float] = ..., minval: Optional[float] = ..., maxval: Optional[float] = ...
325    ) -> Optional[float]: ...
326
327# Functions copied from TurtleScreen:
328
329def clear() -> None: ...
330@overload
331def mode(mode: None = ...) -> str: ...
332@overload
333def mode(mode: str) -> None: ...
334def setworldcoordinates(llx: float, lly: float, urx: float, ury: float) -> None: ...
335def register_shape(name: str, shape: Union[_PolygonCoords, Shape, None] = ...) -> None: ...
336@overload
337def colormode(cmode: None = ...) -> float: ...
338@overload
339def colormode(cmode: float) -> None: ...
340def reset() -> None: ...
341def turtles() -> List[Turtle]: ...
342@overload
343def bgcolor() -> _AnyColor: ...
344@overload
345def bgcolor(color: _Color) -> None: ...
346@overload
347def bgcolor(r: float, g: float, b: float) -> None: ...
348@overload
349def tracer(n: None = ...) -> int: ...
350@overload
351def tracer(n: int, delay: Optional[int] = ...) -> None: ...
352@overload
353def delay(delay: None = ...) -> int: ...
354@overload
355def delay(delay: int) -> None: ...
356def update() -> None: ...
357def window_width() -> int: ...
358def window_height() -> int: ...
359def getcanvas() -> Canvas: ...
360def getshapes() -> List[str]: ...
361def onclick(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ...
362def onkey(fun: Callable[[], Any], key: str) -> None: ...
363def listen(xdummy: Optional[float] = ..., ydummy: Optional[float] = ...) -> None: ...
364def ontimer(fun: Callable[[], Any], t: int = ...) -> None: ...
365@overload
366def bgpic(picname: None = ...) -> str: ...
367@overload
368def bgpic(picname: str) -> None: ...
369@overload
370def screensize(canvwidth: None = ..., canvheight: None = ..., bg: None = ...) -> Tuple[int, int]: ...
371@overload
372def screensize(canvwidth: int, canvheight: int, bg: Optional[_Color] = ...) -> None: ...
373
374onscreenclick = onclick
375resetscreen = reset
376clearscreen = clear
377addshape = register_shape
378if sys.version_info >= (3,):
379    def onkeypress(fun: Callable[[], Any], key: Optional[str] = ...) -> None: ...
380    onkeyrelease = onkey
381
382# Functions copied from _Screen:
383
384def setup(width: float = ..., height: float = ..., startx: Optional[int] = ..., starty: Optional[int] = ...) -> None: ...
385def title(titlestring: str) -> None: ...
386def bye() -> None: ...
387def exitonclick() -> None: ...
388def Screen() -> _Screen: ...
389
390# Functions copied from TNavigator:
391
392def degrees(fullcircle: float = ...) -> None: ...
393def radians() -> None: ...
394def forward(distance: float) -> None: ...
395def back(distance: float) -> None: ...
396def right(angle: float) -> None: ...
397def left(angle: float) -> None: ...
398def pos() -> Vec2D: ...
399def xcor() -> float: ...
400def ycor() -> float: ...
401@overload
402def goto(x: Tuple[float, float], y: None = ...) -> None: ...
403@overload
404def goto(x: float, y: float) -> None: ...
405def home() -> None: ...
406def setx(x: float) -> None: ...
407def sety(y: float) -> None: ...
408@overload
409def distance(x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ...
410@overload
411def distance(x: float, y: float) -> float: ...
412@overload
413def towards(x: Union[TNavigator, Tuple[float, float]], y: None = ...) -> float: ...
414@overload
415def towards(x: float, y: float) -> float: ...
416def heading() -> float: ...
417def setheading(to_angle: float) -> None: ...
418def circle(radius: float, extent: Optional[float] = ..., steps: Optional[int] = ...) -> None: ...
419
420fd = forward
421bk = back
422backward = back
423rt = right
424lt = left
425position = pos
426setpos = goto
427setposition = goto
428seth = setheading
429
430# Functions copied from TPen:
431@overload
432def resizemode(rmode: None = ...) -> str: ...
433@overload
434def resizemode(rmode: str) -> None: ...
435@overload
436def pensize(width: None = ...) -> int: ...
437@overload
438def pensize(width: int) -> None: ...
439def penup() -> None: ...
440def pendown() -> None: ...
441def isdown() -> bool: ...
442@overload
443def speed(speed: None = ...) -> int: ...
444@overload
445def speed(speed: _Speed) -> None: ...
446@overload
447def pencolor() -> _AnyColor: ...
448@overload
449def pencolor(color: _Color) -> None: ...
450@overload
451def pencolor(r: float, g: float, b: float) -> None: ...
452@overload
453def fillcolor() -> _AnyColor: ...
454@overload
455def fillcolor(color: _Color) -> None: ...
456@overload
457def fillcolor(r: float, g: float, b: float) -> None: ...
458@overload
459def color() -> Tuple[_AnyColor, _AnyColor]: ...
460@overload
461def color(color: _Color) -> None: ...
462@overload
463def color(r: float, g: float, b: float) -> None: ...
464@overload
465def color(color1: _Color, color2: _Color) -> None: ...
466def showturtle() -> None: ...
467def hideturtle() -> None: ...
468def isvisible() -> bool: ...
469
470# Note: signatures 1 and 2 overlap unsafely when no arguments are provided
471@overload
472def pen() -> _PenState: ...  # type: ignore
473@overload
474def pen(
475    pen: Optional[_PenState] = ...,
476    *,
477    shown: bool = ...,
478    pendown: bool = ...,
479    pencolor: _Color = ...,
480    fillcolor: _Color = ...,
481    pensize: int = ...,
482    speed: int = ...,
483    resizemode: str = ...,
484    stretchfactor: Tuple[float, float] = ...,
485    outline: int = ...,
486    tilt: float = ...,
487) -> None: ...
488
489width = pensize
490up = penup
491pu = penup
492pd = pendown
493down = pendown
494st = showturtle
495ht = hideturtle
496
497# Functions copied from RawTurtle:
498
499def setundobuffer(size: Optional[int]) -> None: ...
500def undobufferentries() -> int: ...
501@overload
502def shape(name: None = ...) -> str: ...
503@overload
504def shape(name: str) -> None: ...
505
506# Unsafely overlaps when no arguments are provided
507@overload
508def shapesize() -> Tuple[float, float, float]: ...  # type: ignore
509@overload
510def shapesize(stretch_wid: Optional[float] = ..., stretch_len: Optional[float] = ..., outline: Optional[float] = ...) -> None: ...
511
512if sys.version_info >= (3,):
513    @overload
514    def shearfactor(shear: None = ...) -> float: ...
515    @overload
516    def shearfactor(shear: float) -> None: ...
517    # Unsafely overlaps when no arguments are provided
518    @overload
519    def shapetransform() -> Tuple[float, float, float, float]: ...  # type: ignore
520    @overload
521    def shapetransform(
522        t11: Optional[float] = ..., t12: Optional[float] = ..., t21: Optional[float] = ..., t22: Optional[float] = ...
523    ) -> None: ...
524    def get_shapepoly() -> Optional[_PolygonCoords]: ...
525
526def settiltangle(angle: float) -> None: ...
527@overload
528def tiltangle(angle: None = ...) -> float: ...
529@overload
530def tiltangle(angle: float) -> None: ...
531def tilt(angle: float) -> None: ...
532
533# Can return either 'int' or Tuple[int, ...] based on if the stamp is
534# a compound stamp or not. So, as per the "no Union return" policy,
535# we return Any.
536def stamp() -> Any: ...
537def clearstamp(stampid: Union[int, Tuple[int, ...]]) -> None: ...
538def clearstamps(n: Optional[int] = ...) -> None: ...
539def filling() -> bool: ...
540def begin_fill() -> None: ...
541def end_fill() -> None: ...
542def dot(size: Optional[int] = ..., *color: _Color) -> None: ...
543def write(arg: object, move: bool = ..., align: str = ..., font: Tuple[str, int, str] = ...) -> None: ...
544def begin_poly() -> None: ...
545def end_poly() -> None: ...
546def get_poly() -> Optional[_PolygonCoords]: ...
547def getscreen() -> TurtleScreen: ...
548def getturtle() -> Turtle: ...
549
550getpen = getturtle
551
552def onrelease(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ...
553def ondrag(fun: Callable[[float, float], Any], btn: int = ..., add: Optional[Any] = ...) -> None: ...
554def undo() -> None: ...
555
556turtlesize = shapesize
557
558# Functions copied from RawTurtle with a few tweaks:
559
560def clone() -> Turtle: ...
561
562# Extra functions present only in the global scope:
563
564done = mainloop
565