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

Extend the @on decorator so that it will match superclasses #2691

Closed
wants to merge 24 commits into from

Conversation

davep
Copy link
Contributor

@davep davep commented May 30, 2023

This PR seeks to implement the requirement laid out in #2630. In short, the idea is that the the @on decorator should match a given message and any message that inherits from it. To borrow from the issue this stems from, it means that this sort of hierarchy:

class PersonChanged(Message):
    ...

class PersonAdded(PersonChanged):
    ...

class PersonEdited(PersonChanged):
    ...

class PersonRemoved(PersonChanged):
    ...

no longer needs something like this:

@on(PersonAdded)
@on(PersonEdited)
@on(PersonRemoved)
def person_changed(self, event ):
    ...

but can be handles something like this:

@on(PersonChanged)
def person_changed(self, event ):
    ...

One other small change included in this PR is to events.Unmount, which used to inherit from events.Mount; as of this PR it inherits from events.Event; just like all other events. The point of this change being that a developer van safely @on(Mount) without needing to handle fact that events.Unmount would trigger the handler too.

davep added 9 commits May 29, 2023 15:55
See Textualize#2630.

This is, at the moment, an experimental change. This breaks one unit
test (surprisingly *only* one!), but otherwise works as intended. Next up
will be investigating why that one particular test fails.
Leaning on the newer method of matching messages with @on -- this is pretty
much the bit of code that inspired this in the first place.
This doesn't solve the problem I'm trying to solve, but looking at the code
the following day this is neater, I think.
I don't think it makes too much of a difference.
@davep davep added enhancement New feature or request Task labels May 30, 2023
@davep davep marked this pull request as ready for review May 30, 2023 13:35
@rodrigogiraoserrao
Copy link
Contributor

Hold on, shouldn't the title say "[...] it will match subclasses"?

@davep
Copy link
Contributor Author

davep commented May 30, 2023

Hold on, shouldn't the title say "[...] it will match subclasses"?

Possibly. Depends on whose frame of reference you're you're looking from. In this case from the code that goes seeking handlers (in which case it goes looking for any superclasses that hit). From the dev's point of view: t'other way round.

for check_message in message.__class__.__mro__:
# If we've hit something that isn't derived from Message
# we can give up.
if not issubclass(check_message, Message):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may fail in the case of multiple inheritance or mixins. I would hope that nobody uses those in the context of messages, but maybe we should continue rather than break.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, I'll add some testing for this first. The intent here was to not go further up the MRO than Message, to save looping more than necessary (although of course, at the moment, that's only really going to save one more trip round).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test added and the "get out as soon as possible" code changed to "wander up the MRO and check anything that looks like a Message): 02b862c

src/textual/message_pump.py Outdated Show resolved Hide resolved
@rodrigogiraoserrao
Copy link
Contributor

Hold on, shouldn't the title say "[...] it will match subclasses"?

Possibly. Depends on whose frame of reference you're you're looking from. [...]

Ah, of course.

davep added 4 commits May 30, 2023 18:35
Textualize#2691 (review)
being the driving force here.

Also adds a unit test for a non-message mixin into a message class
hierarchy.
The test is added as a passing test, but I don't think this is the result we
really want.
See Textualize#2691 (comment)

The point of this change being that if the developer writes something like:

    @on(Some.Parent)
    @on(Some.Child)
    def some_handler(...):
       ...

then when `Some.Child` is posted, `some_handler` only gets triggered once
for that posting. Until this change it would get triggered twice because
`Some.Child` matches both `Some.Parent` and `Some.Child`.
@davep davep requested a review from willmcgugan May 31, 2023 10:27
davep added 2 commits May 31, 2023 15:35
Not sure yet what the correct result here should be; based on our
conversation so far it seems to be that it's working as intended; but I'm
not sure it's working as intended on purpose. I think there's still a
breaking test to be found and added here.
This was the breakage I was looking for.
@davep davep marked this pull request as draft May 31, 2023 20:10
davep added 7 commits May 31, 2023 22:00
I'm like 90% sure about this. This was a "dump it all and work from scratch"
evening experiment, and I think it does what's needed, but I want to read it
back over again in the morning with a post-coffee brain.

Pushing to the repo so I can review then.

Also added lotsa comments so tomorrow me will know what this evening me was
thinking.
Be 100% sure that combined classes make a hit
Be sure that a combined set of classes with one not matching doesn't match.
@davep davep marked this pull request as ready for review June 1, 2023 09:26
@willmcgugan
Copy link
Collaborator

Solution is good, but there were improvements on efficiency. Closing in favor of #2746

@willmcgugan willmcgugan mentioned this pull request Jun 6, 2023
@davep davep closed this Jun 6, 2023
@davep davep deleted the on-handler-message-hierarchy branch June 13, 2023 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Task
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider the idea of having the @on message handler capture and fire on base messages
3 participants