Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tkinter _Image hack #11721

Open
srittau opened this issue Apr 5, 2024 · 2 comments
Open

Tkinter _Image hack #11721

srittau opened this issue Apr 5, 2024 · 2 comments
Labels
topic: tkinter tkinter-related issues

Comments

@srittau
Copy link
Collaborator

srittau commented Apr 5, 2024

Currently, tkinter uses a hack to mark classes compatible with the image parameter:

# Marker to indicate that it is a valid bitmap/photo image. PIL implements compatible versions
# which don't share a class hierarchy. The actual API is a __str__() which returns a valid name,
# not something that type checkers can detect.
@type_check_only
class _Image: ...

Classes implementing this interface are expected to derive from this stub-only class (or one of its sub-classes). Our Pillow stubs did so. Unfortunately, now that Pillow has its own type annotations, I think it's unreasonable for them to do so at runtime. I think our best bet is to change change _Image to Any here, as this interface can't be represented in our type system.

Cc @Akuli

@srittau srittau added the topic: tkinter tkinter-related issues label Apr 5, 2024
@Akuli
Copy link
Collaborator

Akuli commented Apr 5, 2024

This seems reasonable. Basically, this type alias would be changed to Any:

_ImageSpec: TypeAlias = _Image | str # str can be from e.g. tkinter.image_names()

The most common use cases for tkinter images are setting a window icon with wm_iconphoto() and displaying images in the UI with various image=... keyword arguments. These would become basically Any-typed. IMO that's not a huge problem, because if you do these things wrong, you typically get an error when the program starts, so at least it fails loudly and early.

Another option, if it works, is to just import Pillow's type in tkinter stubs with a # type: ignore. Mypy will treat it as Any when pillow is not installed, but I'm not sure what other type checkers would do.

@Akuli
Copy link
Collaborator

Akuli commented Apr 6, 2024

One more option would be to make a protocol that matches the width, height and paste methods of PIL.ImageTk.PhotoImage. Something like this:

class _PillowPhotoImage:
    def width(self) -> int: ...
    def height(self) -> int: ...
    def paste(self, im: Any, /) -> None: ...

It's unlikely that anything matches this accidentally, and autocompletions will show a somewhat useful _PillowPhotoImage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: tkinter tkinter-related issues
Projects
None yet
Development

No branches or pull requests

2 participants