-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Add tkinter Event class #4200
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
Add tkinter Event class #4200
Conversation
Could you take a look at CI? Need to fix the enum import or the base class :-) |
Right, base class fixed in 0ea4c3e. One question remaining, I gave all the enum members type |
Guess it’s not OK. CI seems to be suggesting that they ought to be declared as |
Sigh. Looks like |
CI pass! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, this looks good to me, but I'm not familiar with the tkinter module.
- enum members are typed by their value, which is often int, but in this case is str: https://github.com/python/cpython/blob/2efe18bf277dd0f38a1d248ae6bdd30947c26880/Lib/tkinter/__init__.py#L147
- Debugging against CI is totally okay, but if you want to have access to older Python interpreters, pyenv works pretty well.
Misc
is the class on which the relevant code seems to be defined too, so that lgtm.send_event
looks right.- Re "??", I'll trust you on whether
Union[str, whatever]
is a more helpful type thanwhatever
. Note that generally typeshed prefers to stick to implementation, so if this causes issues down the road, we'll change it.
height: int | ||
width: int | ||
keycode: int | ||
state: Union[int, str] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you get the type for state
? I'm not familiar with this module, but it might be just int: https://github.com/python/cpython/blob/d31b376bc85dded9d059259737b204e544707d07/Lib/tkinter/__init__.py#L1575
(note that calling repr
on an Event will display the int by an or of bitmasks)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For events of type <Visibility>
, state
is a str
(examples are VisibilityFullyObscured
and VisibilityUnobscured
). However for events of type <ButtonPress>
, it is an int
.
send_event: bool | ||
keysym: str | ||
keysym_num: int | ||
if sys.version_info >= (3, 6): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are at least some code paths where type
and widget
end up as str, but maybe this doesn't actually happen in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are those just the ??
case? Or are there non-??
cases where that can happen too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, not familiar with the module, but I was checking against: https://github.com/python/cpython/blob/d31b376bc85dded9d059259737b204e544707d07/Lib/tkinter/__init__.py#L1587-L1592 where if some lookups fail, we end up with the (presumably) str argument.
But seems possible this might not really happen in practice.
I often end up asserting the type of
How about making I wonder if it's possible to make plain |
I suppose |
I'm currently working on a script that auto-generates some tkinter stubs (hopefully it won't be too insane for creating a pull request to typeshed, lol). If the script ever gets merged to typeshed, then adding a custom I agree that it would be great if
What's your opinion on
i.e. call the bind callback from Tcl and check if it returns the string |
It seems like putting something to every widget is not even necessary: from typing import TypeVar, List
T = TypeVar('T')
class Widget:
def bind(self: T) -> List[T]:
return [self]
class Label(Widget):
pass
reveal_type(Label().bind) # mypy says: Revealed type is 'def () -> builtins.list[foo.Label*]' |
I suppose
I didn’t know it existed :) It seems great, other than that it’s limited to 3.8+ and therefore requires some Python version checks. |
I think an upper bound to |
There is a backwards-compatible way to use
Now that you mention container widgets, I remembered that
Now clicking on the label triggers a callback bound with This behaviour is documented in
One problem with this is that it's possible for a
Now clicking on the frame runs the bind callback with |
In typeshed you can just always use |
Is there a way to make plain The typing module does something similar where |
Hmm. If I do
then plain |
Also, |
Notes regarding this PR:
??
(literally two question marks) for events where those fields are not used and are not applicable. I didn’t bother making most of the fieldsUnion[str, whatever]
, because that seemed more annoying than useful; most of the time you would be writing an event handler for the appropriate type of event and would only access those fields that are applicable for that event. I can make them allUnion[str, whatever]
if you think that’s more appropriate though.send_event
is not documented in thehelp
output, but from inspection it appears to be abool
, so that’s what I made it.widget
Misc
because it can be an actual widget (of some subclass ofBaseWidget
) or it can be atkinter.Tk
which does not extendBaseWidget
, andMisc
is the common base class of those two. I could make it aUnion[BaseWidget, Tk]
if you prefer, or something else.