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

Implement DictItemObserver for observing mutations to a dict #1072

Merged
merged 23 commits into from
May 15, 2020

Conversation

kitchoi
Copy link
Contributor

@kitchoi kitchoi commented May 8, 2020

This PR implements item 9 of #977:

Implement the logic for attaching notifiers when the items of a dict changes

  • Add DictChangeEvent. Note that the definition of DictChangeEvent is not the same as TraitDict.notify, see discussion in Remove "changed" from TraitDict change event #1031
  • Add DictItemObserver that implements the interface of IObserver:
    - return the object for adding/removing notifiers. In this case, the observable is simply an instance of TraitDict.
    - yield the values of the dict for the next observer(s) in an ObserverGraph. values is an obvious choice here because mutables should not be used as keys in dict.
    - Like ListItemObserver, no filtering is done while yielding values for the next observer(s) on the observer graph. If the values are incompatible with the next observers, the latter can complain.
  • Implement IObservable interface in TraitDict. With this, any subclass of TraitDict, e.g. TraitDictObject, can be observed with DictItemObserver (see tests).

Checklist

  • Tests
  • Update API reference (docs/source/traits_api_reference)
  • Update User manual (docs/source/traits_user_manual)
  • Update type annotation hints in traits-stubs

@codecov-io
Copy link

codecov-io commented May 8, 2020

Codecov Report

Merging #1072 into master will decrease coverage by 2.78%.
The diff coverage is 61.17%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1072      +/-   ##
==========================================
- Coverage   76.15%   73.37%   -2.79%     
==========================================
  Files          54       69      +15     
  Lines        6493     8213    +1720     
  Branches     1263     1568     +305     
==========================================
+ Hits         4945     6026    +1081     
- Misses       1205     1808     +603     
- Partials      343      379      +36     
Impacted Files Coverage Δ
traits/api.py 100.00% <ø> (+9.67%) ⬆️
traits/base_trait_handler.py 61.76% <ø> (ø)
traits/ctrait.py 71.07% <ø> (ø)
traits/has_traits.py 72.40% <ø> (-0.37%) ⬇️
traits/observers/_i_notifier.py 0.00% <0.00%> (ø)
traits/observers/_i_observable.py 0.00% <0.00%> (ø)
traits/observers/events.py 0.00% <0.00%> (ø)
traits/traits.py 75.10% <ø> (-2.45%) ⬇️
traits/util/resource.py 15.25% <ø> (ø)
traits/observers/_generated_parser.py 51.96% <51.96%> (ø)
... and 37 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dfc6ffa...a4d851d. Read the comment docs.

@kitchoi kitchoi changed the title Implement DictItemObserver for observing mutations to a list Implement DictItemObserver for observing mutations to a dict May 8, 2020
@kitchoi
Copy link
Contributor Author

kitchoi commented May 11, 2020

Merge conflicts are resulting from API modules and API documentation source shared with other PRs.
I was debating between putting the API modules together later or noisy merge conflicts now. I ended up choosing to deal with trivial merge conflicts instead of risking things being left out of the API modules/doc. Will see how well this goes...



class DictChangeEvent:
""" Event object to represent mutations on a dict.
Copy link
Member

Choose a reason for hiding this comment

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

To avoid accidents, I think it's worth adding a explicit sentence here about the difference between this API and the removed / added / changed API. Otherwise I think people will glance at this, and just assume that it behaves like the existing API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

SGTM

def __eq__(self, other):
""" Return true if this observer is equal to the given one."""
return (
type(self) is type(other)
Copy link
Member

@mdickinson mdickinson May 14, 2020

Choose a reason for hiding this comment

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

We're still inconsistent across the codebase about using type (e.g., as here) versus using .__class__ (e.g., in the __repr__ for DictChangeEvent). They're subtly different, and some of the new typing machinery being introduced in recent Python versions is enlarging that difference (e.g., in Python 3.9, list[int] has a different __class__ from its type).

I think we actually want to use __class__ consistently throughout the codebase, despite the general rule that one shouldn't generally use dunder attributes and methods directly as a consumer.

Not something that should be changed in this PR; just something to think about.



def create_observer(**kwargs):
""" Convenient function for creating DictItemObserver with default values.
Copy link
Member

Choose a reason for hiding this comment

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

Convenience

Copy link
Member

@mdickinson mdickinson left a comment

Choose a reason for hiding this comment

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

LGTM; one docstring nitpick.

@mdickinson
Copy link
Member

Still LGTM, modulo conflicts.

@kitchoi
Copy link
Contributor Author

kitchoi commented May 15, 2020

Thanks! I put this side-by-side with the List counterpart and they look consistent as far as I can tell. Will merge when CI is green.

@kitchoi kitchoi merged commit 7c8922c into master May 15, 2020
@kitchoi kitchoi deleted the 977-dict-item-observer branch May 15, 2020 08:41
@kitchoi
Copy link
Contributor Author

kitchoi commented May 15, 2020

I put this side-by-side with the List counterpart and they look consistent as far as I can tell.

I knew I am going to spot inconsistencies later, and I did find one after merge.
Will open a separate PR.

@kitchoi
Copy link
Contributor Author

kitchoi commented May 15, 2020

Will open a separate PR.

Here it is: #1085

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.

3 participants