From 954ce8c7031bda4017c86f0757c635bd68f9ac0d Mon Sep 17 00:00:00 2001 From: Akuli Date: Sat, 8 Aug 2020 15:14:52 +0300 Subject: [PATCH] create _tkinter stub (#4372) --- pyproject.toml | 1 + stdlib/3/_tkinter.pyi | 93 +++++++++++++++++++++++++++++++++++ stdlib/3/tkinter/__init__.pyi | 53 ++++++++++++++++---- stdlib/3/tkinter/ttk.pyi | 6 +-- 4 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 stdlib/3/_tkinter.pyi diff --git a/pyproject.toml b/pyproject.toml index 0d3384262..bf2789700 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ extra_standard_library = [ "_curses", "_markupbase", "_random", + "_tkinter", "_weakrefset", "genericpath", "opcode", diff --git a/stdlib/3/_tkinter.pyi b/stdlib/3/_tkinter.pyi new file mode 100644 index 000000000..d6ff308d3 --- /dev/null +++ b/stdlib/3/_tkinter.pyi @@ -0,0 +1,93 @@ +from typing import Any, Tuple, Union + +# _tkinter is meant to be only used internally by tkinter, but some tkinter +# functions e.g. return _tkinter.Tcl_Obj objects. Tcl_Obj represents a Tcl +# object that hasn't been converted to a string. +# +# There are not many ways to get Tcl_Objs from tkinter, and I'm not sure if the +# only existing ways are supposed to return Tcl_Objs as opposed to returning +# strings. Here's one of these things that return Tcl_Objs: +# +# >>> import tkinter +# >>> text = tkinter.Text() +# >>> text.tag_add('foo', '1.0', 'end') +# >>> text.tag_ranges('foo') +# (, ) +class Tcl_Obj: + string: str # str(tclobj) returns this + typename: str + +class TclError(Exception): ... + +# This class allows running Tcl code. Tkinter uses it internally a lot, and +# it's often handy to drop a piece of Tcl code into a tkinter program. Example: +# +# >>> import tkinter, _tkinter +# >>> tkapp = tkinter.Tk().tk +# >>> isinstance(tkapp, _tkinter.TkappType) +# True +# >>> tkapp.call('set', 'foo', (1,2,3)) +# (1, 2, 3) +# >>> tkapp.eval('return $foo') +# '1 2 3' +# >>> +# +# call args can be pretty much anything. Also, call(some_tuple) is same as call(*some_tuple). +# +# eval always returns str because _tkinter_tkapp_eval_impl in _tkinter.c calls +# Tkapp_UnicodeResult, and it returns a string when it succeeds. +class TkappType: + # Please keep in sync with tkinter.Tk + def call(self, __command: Union[str, Tuple[Any, ...]], *args: Any) -> str: ... + def eval(self, __script: str) -> Any: ... + adderrorinfo: Any + createcommand: Any + createfilehandler: Any + createtimerhandler: Any + deletecommand: Any + deletefilehandler: Any + dooneevent: Any + evalfile: Any + exprboolean: Any + exprdouble: Any + exprlong: Any + exprstring: Any + getboolean: Any + getdouble: Any + getint: Any + getvar: Any + globalgetvar: Any + globalsetvar: Any + globalunsetvar: Any + interpaddr: Any + loadtk: Any + mainloop: Any + quit: Any + record: Any + setvar: Any + split: Any + splitlist: Any + unsetvar: Any + wantobjects: Any + willdispatch: Any + +ALL_EVENTS: int +FILE_EVENTS: int +IDLE_EVENTS: int +TIMER_EVENTS: int +WINDOW_EVENTS: int + +DONT_WAIT: int +EXCEPTION: int +READABLE: int +WRITABLE: int + +TCL_VERSION: str +TK_VERSION: str + +# TODO: figure out what these are (with e.g. help()) and get rid of Any +TkttType: Any +_flatten: Any +create: Any +getbusywaitinterval: Any +setbusywaitinterval: Any diff --git a/stdlib/3/tkinter/__init__.pyi b/stdlib/3/tkinter/__init__.pyi index 894f51153..d1932d4d4 100644 --- a/stdlib/3/tkinter/__init__.pyi +++ b/stdlib/3/tkinter/__init__.pyi @@ -1,3 +1,4 @@ +import _tkinter import sys from enum import Enum from tkinter.constants import * # noqa: F403 @@ -5,13 +6,13 @@ from types import TracebackType from typing import Any, Callable, Dict, Generic, List, Optional, Tuple, Type, TypeVar, Union, overload from typing_extensions import Literal, TypedDict -TclError: Any +TclError = _tkinter.TclError wantobjects: Any TkVersion: Any TclVersion: Any -READABLE: Any -WRITABLE: Any -EXCEPTION: Any +READABLE = _tkinter.READABLE +WRITABLE = _tkinter.WRITABLE +EXCEPTION = _tkinter.EXCEPTION # If a manual page mentions Tk_GetAnchor or refers to another manual page named # 'options', then it means this. Note that some ttk widgets have other things @@ -142,6 +143,7 @@ def getboolean(s): ... # This class is the base class of all widgets. Don't use BaseWidget or Widget # for that because Tk doesn't inherit from Widget or BaseWidget. class Misc: + tk: _tkinter.TkappType def destroy(self): ... def deletecommand(self, name): ... def tk_strictMotif(self, boolean: Optional[Any] = ...): ... @@ -431,7 +433,6 @@ class Wm: class Tk(Misc, Wm): master: Optional[Any] children: Dict[str, Any] - tk: Any def __init__( self, screenName: Optional[str] = ..., @@ -441,11 +442,43 @@ class Tk(Misc, Wm): sync: bool = ..., use: Optional[str] = ..., ) -> None: ... - def loadtk(self) -> None: ... + def loadtk(self) -> None: ... # differs from _tkinter.TkappType.loadtk def destroy(self) -> None: ... def readprofile(self, baseName: str, className: str) -> None: ... report_callback_exception: Callable[[Type[BaseException], BaseException, TracebackType], Any] - def __getattr__(self, attr: str) -> Any: ... + # Tk has __getattr__ so that tk_instance.foo falls back to tk_instance.tk.foo + # Please keep in sync with _tkinter.TkappType + call: Callable[..., str] + eval: Callable[[str], Any] + adderrorinfo: Any + createcommand: Any + createfilehandler: Any + createtimerhandler: Any + deletecommand: Any + deletefilehandler: Any + dooneevent: Any + evalfile: Any + exprboolean: Any + exprdouble: Any + exprlong: Any + exprstring: Any + getboolean: Any + getdouble: Any + getint: Any + getvar: Any + globalgetvar: Any + globalsetvar: Any + globalunsetvar: Any + interpaddr: Any + mainloop: Any + quit: Any + record: Any + setvar: Any + split: Any + splitlist: Any + unsetvar: Any + wantobjects: Any + willdispatch: Any def Tcl(screenName: Optional[Any] = ..., baseName: Optional[Any] = ..., className: str = ..., useTk: bool = ...): ... @@ -908,8 +941,10 @@ class OptionMenu(Menubutton): class Image: name: Any - tk: Any - def __init__(self, imgtype, name: Optional[Any] = ..., cnf=..., master: Optional[Any] = ..., **kw): ... + tk: _tkinter.TkappType + def __init__( + self, imgtype, name: Optional[Any] = ..., cnf=..., master: Optional[Union[Misc, _tkinter.TkappType]] = ..., **kw + ): ... def __del__(self): ... def __setitem__(self, key, value): ... def __getitem__(self, key): ... diff --git a/stdlib/3/tkinter/ttk.pyi b/stdlib/3/tkinter/ttk.pyi index 39c3dc0dd..23af5ada9 100644 --- a/stdlib/3/tkinter/ttk.pyi +++ b/stdlib/3/tkinter/ttk.pyi @@ -1,6 +1,6 @@ +import _tkinter import sys import tkinter -from tkinter import Event from typing import Any, Callable, List, Optional, overload from typing_extensions import Literal @@ -9,7 +9,7 @@ def setup_master(master: Optional[Any] = ...): ... class Style: master: Any - tk: Any + tk: _tkinter.TkappType def __init__(self, master: Optional[Any] = ...): ... def configure(self, style, query_opt: Optional[Any] = ..., **kw): ... def map(self, style, query_opt: Optional[Any] = ..., **kw): ... @@ -154,7 +154,7 @@ class Treeview(Widget, tkinter.XView, tkinter.YView): self, tagname: str, sequence: Optional[str] = ..., - callback: Optional[Callable[[Event[Treeview]], Optional[Literal["break"]]]] = ..., + callback: Optional[Callable[[tkinter.Event[Treeview]], Optional[Literal["break"]]]] = ..., ) -> str: ... @overload def tag_bind(self, tagname: str, sequence: Optional[str], callback: str) -> None: ...