Where do VSCode’s type hints for tkinter.Canvas come from?

I found something that is bugging my mind.

An important feature from VSCode is the type-hinting I get when writing a tkinter class that takes **kw. Here is an example:

vscode showing useful information about the **kw variable in Tk.Canvas()

Now I’m trying to make a child class from the Tk.Canvas() class, and luckily vscode already did the hard work of writing this down:

class MyCanvas(Tk.Canvas):
    def __init__(self, master: Misc | None, cnf: dict[str, Any] | None, *, background: _Color, bd: _ScreenUnits, bg: _Color, border: _ScreenUnits, borderwidth: _ScreenUnits, closeenough: float, confine: bool, cursor: _Cursor, height: _ScreenUnits, highlightbackground: _Color, highlightcolor: _Color, highlightthickness: _ScreenUnits, insertbackground: _Color, insertborderwidth: _ScreenUnits, insertofftime: int, insertontime: int, insertwidth: _ScreenUnits, name: str, offset: Any, relief: _Relief, scrollregion: Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits] | Tuple[()], selectbackground: _Color, selectborderwidth: _ScreenUnits, selectforeground: _Color, state: Literal["normal", "disabled"], takefocus: _TakeFocusValue, width: _ScreenUnits, xscrollcommand: _XYScrollCommand, xscrollincrement: _ScreenUnits, yscrollcommand: _XYScrollCommand, yscrollincrement: _ScreenUnits) -> None:
        super().__init__(master=master, cnf=cnf, background=background, bd=bd, bg=bg, border=border, borderwidth=borderwidth, closeenough=closeenough, confine=confine, cursor=cursor, height=height, highlightbackground=highlightbackground, highlightcolor=highlightcolor, highlightthickness=highlightthickness, insertbackground=insertbackground, insertborderwidth=insertborderwidth, insertofftime=insertofftime, insertontime=insertontime, insertwidth=insertwidth, name=name, offset=offset, relief=relief, scrollregion=scrollregion, selectbackground=selectbackground, selectborderwidth=selectborderwidth, selectforeground=selectforeground, state=state, takefocus=takefocus, width=width, xscrollcommand=xscrollcommand, xscrollincrement=xscrollincrement, yscrollcommand=yscrollcommand, yscrollincrement=yscrollincrement)

But this definition is quite wrong: it treats the properties as vars instead of **kw, and references classes that aren’t defined, like _Color and _ScreenUnits. So I went to the Tk.Canvas.__init__() definition to see what is going on, and I found this:

def __init__(self, master=None, cnf={}, **kw):
        """Construct a canvas widget with the parent MASTER.

        Valid resource names: background, bd, bg, borderwidth, closeenough,
        confine, cursor, height, highlightbackground, highlightcolor,
        highlightthickness, insertbackground, insertborderwidth,
        insertofftime, insertontime, insertwidth, offset, relief,
        scrollregion, selectbackground, selectborderwidth, selectforeground,
        state, takefocus, width, xscrollcommand, xscrollincrement,
        yscrollcommand, yscrollincrement."""
        Widget.__init__(self, master, 'canvas', cnf, kw)

So here I’m confused, because in the class definition there isn’t a single type hint. So where does all this “type hinting” I’m getting come from? Is there a way to make it appear in my child class’s **kw?


VSCode’s type hints for the python standard library come from Typeshed, a repository of stub files for the standard library (see here: How does VS Code get type hints?). The stub for Tk.Canvas can be found here on github. At the top of that file, you can find definitions for _Color, _ScreenUnits, etc. (I agree that it seems a little buggy for VSCode to be providing these in autocompletes without telling you their definitions or even where these “foreign” types come from.)

Lines 84-111 of the stub file as of 2021-08-28:

_T = TypeVar("_T")
_TkinterSequence = Union[List[_T], Tuple[_T, ...]]
_TkinterSequence2D = Union[List[List[_T]], List[Tuple[_T, ...]], Tuple[List[_T], ...], Tuple[Tuple[_T, ...], ...]]

# Some widgets have an option named -compound that accepts different values
# than the _Compound defined here. Many other options have similar things.
_Anchor = Literal["nw", "n", "ne", "w", "center", "e", "sw", "s", "se"]  # manual page: Tk_GetAnchor
_Bitmap = str  # manual page: Tk_GetBitmap
_ButtonCommand = Union[str, Callable[[], Any]]  # return value is returned from Button.invoke()
_CanvasItemId = int
_Color = str  # typically '#rrggbb', '#rgb' or color names.
_Compound = Literal["top", "left", "center", "right", "bottom", "none"]  # -compound in manual page named 'options'
_Cursor = Union[str, Tuple[str], Tuple[str, str], Tuple[str, str, str], Tuple[str, str, str, str]]  # manual page: Tk_GetCursor
_EntryValidateCommand = Union[
    Callable[[], bool], str, _TkinterSequence[str]
]  # example when it's sequence:  entry['invalidcommand'] = [entry.register(print), '%P']
_ImageSpec = Union[_Image, str]  # str can be from e.g. tkinter.image_names()
_Padding = Union[
    Tuple[_ScreenUnits, _ScreenUnits],
    Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits],
    Tuple[_ScreenUnits, _ScreenUnits, _ScreenUnits, _ScreenUnits],
_Relief = Literal["raised", "sunken", "flat", "ridge", "solid", "groove"]  # manual page: Tk_GetRelief
_ScreenUnits = Union[str, float]  # manual page: Tk_GetPixels
_XYScrollCommand = Union[str, Callable[[float, float], Any]]  # -xscrollcommand and -yscrollcommand in 'options' manual page
_TakeFocusValue = Union[int, Literal[""], Callable[[str], Optional[bool]]]  # -takefocus in manual page named 'options'

Also, note that all parameters after a bare * in a function definition are keyword-only parameters. As such, I don’t agree that the type-annotation in typeshed for Tk.canvas.__init__ is wrong — it doesn’t look to me as though they’ve marked any parameters as positional when they should be marked as keyword-only.