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

[doc]Update doc of AliasProperty #6316

Merged
merged 2 commits into from
May 21, 2019

Conversation

pythonic64
Copy link
Contributor

Improved doc of AliasProperty better explains setter method and bind argument.

If your want to cache the value returned by getter then pass `cache=True`.
Usually `bind` list should contain all Kivy properties used in getter
method. If you're setting a property from `bind` list then you shouldn't
`return True` in setter as that will dispatch new value twice.
Copy link
Member

Choose a reason for hiding this comment

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

This is not necessarily correct. For example:

def getter(self):
    return self._value

def setter(self, value):
    self.x = value * 25
    self._value = value
    return True

prop = AliasProperty(getter, setter, bind=['x'], cache=True)

Even though we set x in the setter, we still need to return True, otherwise it will have the incorrect value.

So we shouldn't advise people to return True/False based on what was set in the setter, but rather always recommend to return True if it was changed. The original comment

If x were to be an instance level attribute and not Kivy property then you have to return True from setter to dispatch value of right

is also misleading in this way and should instead just say that it needs to return True if we want it to dispatch.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are so many cases with AliasProperty.
If you swap x and _value lines in setter:

def setter(self, value):
    self._value = value
    self.x = value * 25
    return True

and still return True then prop value will be dispatched twice with same value, first when x is set and again when True is returned.

Do you have idea on how to better phrase that paragraph so that is clear when user should return True? I'm right now out of ideas :)

Copy link
Contributor Author

@pythonic64 pythonic64 May 20, 2019

Choose a reason for hiding this comment

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

Maybe we can update set method of AliasProperty from this:

cpdef set(self, EventDispatcher obj, value):
    cdef PropertyStorage ps = obj.__storage[self._name]
    if ps.setter(obj, value):
        if self.use_cache:
            if ps.alias_initial:
                ps.alias_initial = 0
            ps.value = ps.getter(obj)
        self.dispatch(obj)
    elif self.force_dispatch:
        self.dispatch(obj)

to this:

cpdef set(self, EventDispatcher obj, value):
    cdef PropertyStorage ps = obj.__storage[self._name]
    if ps.setter(obj, value):
        cdef int changed = 1
        if self.use_cache:
            changed = 0
            dvalue = ps.getter(obj)
            if dvalue != ps.value:
                if ps.alias_initial:
                    ps.alias_initial = 0
                ps.value = dvalue
                changed = 1
        if changed:
            self.dispatch(obj)
    elif self.force_dispatch:
        self.dispatch(obj)

Then we can tell the user to return True in setter to accept value, but value will be dispatched only if it has changed.

Copy link
Member

Choose a reason for hiding this comment

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

You are right that it would be dispatched twice, but I think it's ok. It's better to dispatch multiple times (after all that's how it would generally work), then not dispatch when needed. Kivy doesn't really make a guarantee that properties won't dispatch even if the value is the same (although we do try to prevent that if possible). We just promise that properties will definitely dispatch if they are changed.

As you say, it's hard to say something meaningful here in the docs because we could have many different situations. That's why I think saying something like, if you return True it will cause a dispatch which one should do to when the property value has changed, but keep in mind that the property could already have dispatched the changed value if a kivy property the alias property is bound was set in the setter, causing a second dispatch if the setter returns True. is better. Because this makes no recommendation, but just describes the behavior.

We can definitely change set to what you suggest, but that would change the interpretation of returning True from meaning we should dispatch to mean that the value may have changed so maybe we should dispatch. This change may be a compatibility break and I'm not sure it is worth to do unless this comes up as an actual issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll update pr with your suggestions.

Function to use as a property setter. Callbacks bound to the
alias property won't be called when the property is set (e.g.
`right = 10`), unless the setter returns `True`.
Function to use as a property setter.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why you removed this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed sentence is partially true, because callbacks will be also dispatched when some of binded properties changes and getter returns new value.
I thought that it would be better to explain in text above how setter should work and don't repeat same thing in Parameters section.

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 it is better to give a very short summary here, even if it was already explained earlier because sometimes I don't get the full implication from the example and I want a short summary to make sure I understood the implications. Repeating it twice gives me chance to make sure I understood by comparing what I understand the two places to say.

So I'd say it's good to fix it to give a very short and concise summary here and for bind.

Properties to observe for changes, as property name strings.
Changing values of this properties will dispatch value of the
alias property.
Properties to observe for changes as property name strings.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure why you removed this either?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same as the answer above. That sentence is partially true as new value will be dispatched only when binded property changes and getter returns new value.
If getter is doing something like clamping (min(max(x, min_value), max_value)) and returns the same value then property won't get dispatched.

@matham matham merged commit b5540af into kivy:master May 21, 2019
@matham matham changed the title Update doc of AliasProperty [doc]Update doc of AliasProperty May 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants