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