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