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

Animation: Fix kivy.animation.Sequence and kivy.animation.Parallel consistency #5926

Merged
merged 16 commits into from
May 7, 2020

Conversation

gottadiveintopython
Copy link
Member

@gottadiveintopython gottadiveintopython commented Aug 31, 2018

@matham
Copy link
Member

matham commented Aug 31, 2018

I wonder if has_animation_properties is a better name? And maybe it's better if its a @property?

@matham
Copy link
Member

matham commented Aug 31, 2018

Oh, Never mind, the function already exists in master. I'll let someone with animation usage review it.

@gottadiveintopython
Copy link
Member Author

yep it override Animation.have_prop...()
Thanks for the review.

tshirtman
tshirtman previously approved these changes Aug 31, 2018
Copy link
Member

@tshirtman tshirtman left a comment

Choose a reason for hiding this comment

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

Looks good to me, great that you added tests to cover the case, tests passed here and the change is straightforward, it's a bit sad to have duplication here, but maybe refactoring to remove it would make things more complicated (a new parent class?), i'm fine with that for now.

@gottadiveintopython
Copy link
Member Author

Hi, and thanks for the review.

it's a bit sad to have duplication here

yep and I didn't come up with any good idea. Should I fix that like this?

class MoreNestedSequentialAnimationTestCase(unittest.TestCase):  # changed base class

    def setUp(self):
        ...

    def tearDown(self):
        ...

    def test_have_properties_to_animate(self):  # test only this method
        ...

And regardless of that, I'll fix test_have_properties_to_animate() like this

    def test_have_properties_to_animate(self):
        self.assertFalse(self.a.have_properties_to_animate(self.w))
        self.a.start(self.w)
        self.assertTrue(self.a.have_properties_to_animate(self.w))
        self.a.stop(self.w)
        self.assertFalse(self.a.have_properties_to_animate(self.w))

which should be better than current code.

@tshirtman
Copy link
Member

I meant for the Sequence and Parallel to have a common method, (but i'm not sure which meaning of "like" you used here, if you meant "in the same way as", then ok). i.e:

class CompoundAnimation(Animation):
    def have_property_to_animate(self, widget):
        …

class Sequence(CompoundAnimation):
    …

class Parallel(CompoundAnimation):
    …

i think is slightly better than having the exact same method in two classes.

@gottadiveintopython
Copy link
Member Author

ah I understand what you mean.

stop(), stop_property(), cancel(), have_properties_to_animate() are completely same. So moving them to CompoundAnimation, the base class. I feel that doing that loose some flexibility. But anyawys I'm doing that now.

@gottadiveintopython
Copy link
Member Author

gottadiveintopython commented Sep 1, 2018

I'm analyzing several things, so don't merge this PR yet

@tshirtman tshirtman added the Status: On-hold PR is on hold and should not be merged until issues inside are resolved label Sep 1, 2018
@gottadiveintopython
Copy link
Member Author

gottadiveintopython commented Sep 1, 2018

Sequence and Parallel are really buggy while Animation is not.
If I continue fixing those bugs, this PR will become not related to the issue(#5443).
So I'm probably going to make another PR since the issue was already fixed.

@tshirtman
Copy link
Member

Yes, there are certainly bugs left in them, thank you for looking into it.

@gottadiveintopython
Copy link
Member Author

np :)
well I updated the PR. Can you review it?

@gottadiveintopython
Copy link
Member Author

thanks

@property
def transition(self):
# This property is impossible to implement
raise NotImplementedError()
Copy link
Member

Choose a reason for hiding this comment

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

I think adding a message to the exception would be better, but that got me thinking, maybe we could just use AttributeError("Can't lookup transition attribute of a CompoundAnimation") since this is accessed as an attribute. What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep I agree with adding a message to the exception.
And about AttributeError, I can't decide because for me both looks fine. But according to the reference, AttributeError might be better.

Copy link
Member Author

Choose a reason for hiding this comment

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

Because NotImplementedError means real implementation required, which is not our case.
so yeah AttibuteError is better I think.

@tshirtman tshirtman removed the Status: On-hold PR is on hold and should not be merged until issues inside are resolved label Sep 2, 2018
@gottadiveintopython gottadiveintopython changed the title Fix #5443 [WIP] fix kivy.animation.Sequence and kivy.animation.Parallel Sep 6, 2018
@gottadiveintopython gottadiveintopython changed the title [WIP] fix kivy.animation.Sequence and kivy.animation.Parallel fix kivy.animation.Sequence and kivy.animation.Parallel Sep 17, 2018
@gottadiveintopython
Copy link
Member Author

@tshirtman Hi, is it better to git rebase master and rewrite unit tests in pytest-style? or better to keep the current state?

@tshirtman
Copy link
Member

Hey, if you are willing to, rebasing/updating would be great.

@gottadiveintopython gottadiveintopython changed the title [base/animation]fix kivy.animation.Sequence and kivy.animation.Parallel [WIP][base/animation]fix kivy.animation.Sequence and kivy.animation.Parallel May 3, 2020
@gottadiveintopython
Copy link
Member Author

gottadiveintopython commented May 3, 2020

Parallel never fires on_progress, and I think it's a corrent behavior. But it might confuse the user, so we may need to document it.

Or maybe Parallel should fire on_progress only when Parallel.anim1 fires on_progress.

# for example: using ChainMap
d = dict(self.anim1.animated_properties)
d.update(self.anim2.animated_properties)
return d
Copy link
Member Author

@gottadiveintopython gottadiveintopython May 3, 2020

Choose a reason for hiding this comment

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

Might be better not to use ChainMap. Because if we re-implement it like this:

    @property
    def animated_properties(self):
        return ChainMap(self.anim2.animated_properties, self.anim1.animated_properties)

the user will be able to write anim2.animated_properties. The following implementation might be better.

    @property
    def animated_properties(self):
        return {**self.anim1.animated_properties, **self.anim2.animated_properties, }

Copy link
Member

Choose a reason for hiding this comment

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

in both case it's an object that is returned to the user, that they can write to, but that doesn't mean they can write to animation.animated_properties, unless the property defines a setter.

Copy link
Member Author

@gottadiveintopython gottadiveintopython May 3, 2020

Choose a reason for hiding this comment

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

Oh sorry, I meant this part

Lookups search the underlying mappings successively until a key is found. In contrast, writes, updates, and deletions only operate on the first mapping.

in the doc.

To prevent the user from writing to the underlying dictionaries(anim1.animated_properties and anim2.animated_properties), we need to implement it like either of

@property
def animated_properties(self):
    return {**self.anim1.animated_properties, **self.anim2.animated_properties, }

or

@property
def animated_properties(self):
    return ChainMap({}, self.anim2.animated_properties, self.anim1.animated_properties)

Copy link
Member

Choose a reason for hiding this comment

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

ok, that makes sense indeed. I guess the second one is a bit more efficient, as it doesn't unnecessarily copy data around, while still allowing to update the values for this animation (as they'll be saved in the first dict, they'll override values for the same key in the other dicts), and also they'll reflect updates to the animated properties of the underlying animations, in case they happen (and unless an overriding value has been put in the first dict, of course).

@tshirtman
Copy link
Member

Parallel never fires on_progress, and I think it's a corrent behavior. But it might confuse the user, so we may need to document it.

Or maybe Parallel should fire on_progress only when Parallel.anim1 fires on_progress.

hm, if we can't then it's better not to document, i don't see how only firing for anim1 would be correct, ideally it would fire for both, and have the progress value take both durations into account (so if anim 1 is 3s and anim 2 is 2s, 1s into the first animation, we'd get progress at 0.2, 1/5th of the total), but i didn't check how hard it would be to implement that.

@gottadiveintopython
Copy link
Member Author

we'd get progress at 0.2, 1/5th of the total

Sounds like you are confusing Sequence with Parallel. But anyways It may be better to keep the current implementation. If we change it to fire on_progress, it probably impact the performance, because on_progress usually is fired very frequently.

if we can't then it's better not to document

Ok, got it.

@tshirtman
Copy link
Member

tshirtman commented May 3, 2020

we'd get progress at 0.2, 1/5th of the total

Sounds like you are confusing Sequence with Parallel. But anyways It may be better to keep the current implementation. If we change it to fire on_progress, it probably impact the performance, because on_progress usually is fired very frequently.

🤦 you are right, maybe we could report based on the longest, but yeah, in any case, no need to think about that in this PR, it would be a new feature imho, to be evaluated independently.

if we can't then it's better not to document

Ok, got it.

👍

@gottadiveintopython gottadiveintopython changed the title [WIP][base/animation]fix kivy.animation.Sequence and kivy.animation.Parallel [base/animation]fix kivy.animation.Sequence and kivy.animation.Parallel May 3, 2020
@gottadiveintopython
Copy link
Member Author

@tshirtman
I believe the PR is mergeable. Could you check if it's ok or not?

we could report based on the longest

Yeah I agree with that way if we implement it.

@gottadiveintopython
Copy link
Member Author

gottadiveintopython commented May 7, 2020

@tshirtman I mean Could you approve the PR?

@tshirtman
Copy link
Member

sorry i missed the update (again). I'll approve now.

@tshirtman tshirtman merged commit 8675387 into kivy:master May 7, 2020
@gottadiveintopython gottadiveintopython deleted the fix_5443 branch May 8, 2020 04:14
@matham matham added this to the 2.0.0 milestone Oct 28, 2020
@matham matham changed the title [base/animation]fix kivy.animation.Sequence and kivy.animation.Parallel Animation: Fix kivy.animation.Sequence and kivy.animation.Parallel consistency Nov 14, 2020
@matham matham added the Component: core-widget properties, eventdispatcher, widget.py, animation label Nov 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: core-widget properties, eventdispatcher, widget.py, animation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

kivy.animation.Sequence sends "on_complete" event while animation is still in progress
3 participants