1

I have a callback

from tkinter import font, ttk

class Foo(ttk.Frame):
    def set_font_cb(self, event: tk.Event) -> None:
        event.widget.configure(font=font.Font(...))

And this creates in mypy as well as in pylance an error:

  • mypy: error: Unexpected keyword argument "font" for "configure" of "Misc" [call-arg]
  • pylance: No parameter named "font"

What is the fix for this? I cannot find a reference what is actually supported as kw arguments and what the correct would be to change the font.

2
  • The problem is that tkinter is a thin wrapper over tcl/tk (a weakly typed language) which is why tkinter can't really be strongly typed. I don't know much about mypy nor pylance but I would suggest that you disable the static type checking around tkinter code Commented Oct 1 at 12:59
  • It is not known what event.widget is, so how can you be sure that it has the font attribute? Since set_font_cb() is a method of a ttk.Frame class, event.widget may be most probably an instance of ttk.Frame which does not have font attribute. Commented Oct 1 at 13:08

1 Answer 1

1

The linters are complaining because Misc (the catch-all type for tkinter widgets) doesn't specifically have a font attribute. If the widget passed in by event.widget is something like a Label (i.e. something that does understand what font is), then you'll just need to be more specific with your type checking to keep pylance / mypy happy

import tkinter as tk  # this was missing, so I added it
from tkinter import font, ttk

class Foo(ttk.Frame):
    def set_font_cb(self, event: tk.Event) -> None:
        widget = event.widget
        if isinstance(widget, tk.Label):  # check if the given widget is a Label (or whatever)
            widget.configure(font=font.Font())

NB: the gist is to just use isinstance to check if the type of widget matches what you're expecting to configure - it doesn't have to be a Label, that's just what I've used here

Sign up to request clarification or add additional context in comments.

7 Comments

If you use this method, make sure to add an else that raises an error. Otherwise later if you modify the code, you might have a hard time debugging why your font isn't being set
Yep, good advice!
OP code will already raise exception if event.widget does not have font option, so what is the point of your suggestion?
OP's code would raise an error but the code from this answer won't. If the widget gets changed (eg. from tk.Label to tk.Text), the if statement will be false so the font changing code will be skipped.
Instead of it-else-raise consider assert - it's very commonly used in typed python code to say to the typechecker "yes, I'm sure about this type or will get a crash otherwise".
That is better as long as the assert either has a good message or is self-documenting. I have seen projects with asserts to make the static checker happy while not providing any useful information when the error occurs.
As ever we live and die by the inline documentation! assert is a good move here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.