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

Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] #354

Merged
merged 16 commits into from
Jan 14, 2021

Conversation

kitchoi
Copy link
Contributor

@kitchoi kitchoi commented Oct 28, 2020

Closes #291

This PR allows on_trait_change("name_items") to be migrated to observe("name:items") where the name is defined as an ExtensionPoint trait.

After considering all the constraints and alternative approach (see #291), I have come to the conclusion that the support needs to happen by caching the TraitList returned for the ExtensionPoint and making it impossible to mutate the list directly. Having a persisted list that can change is, strictly speaking, what on_trait_change("x_items") or observe("x:items") assumes.

This means the list of extensions has to be maintained not just on the extension registry, but on the object with the extension point as well. This requires fair amount of efforts to keep these values in-sync. This PR still treats the extension registry as the single source of truth as to what extensions are available. The ExtensionPoint remains to be a proxy to query values in an extension registry.

Caution: This implementation requires Traits 6.1, as it imports TraitList from traits.trait_list_object. We should decide if it is necessary to phase in Traits 6.1. Should it be decided that the next release of Envisage will still support Traits 6.0, some additional compatibility layer will be needed for this PR. Edited: but I don't think it would be much (We just need to roll the old ExtensionPoint definition for that, that's all.), or this PR can be considered for merging after next release.

This is achieved by caching the value of ExtensionPoint and make it
impossible to mutate the list directly.
envisage/plugin.py Outdated Show resolved Hide resolved

# We shouldn't get a trait event here because we haven't accessed the
# extension point yet!
self.assertEqual(None, listener.obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is removed because it is testing the behaviour noted in the "fixme" comment:

# fixme: If the extension point has not been accessed then the
# provider extension registry can't work out what has changed, so it
# won't fire a changed event.

The "fixme" is now fixed.

Copy link
Contributor Author

@kitchoi kitchoi left a comment

Choose a reason for hiding this comment

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

I will to check for cycle references here, marking as WIP for a bit.

envisage/extension_point.py Outdated Show resolved Hide resolved
envisage/extension_point.py Outdated Show resolved Hide resolved
@kitchoi kitchoi changed the title Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] [WIP] Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] Oct 29, 2020
The reference only serves to support some edge cases where
the extension point values become out-of-sync because the listeners
are not connected yet. Once the listeners are connected the values
are refreshed. So all in all it is not worth keeping the reference,
as one will then need to use weakref to avoid cycle references,
and special handling in the pickling logic to handle that weakref.
@kitchoi kitchoi changed the title [WIP] Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] Oct 29, 2020
@kitchoi
Copy link
Contributor Author

kitchoi commented Oct 29, 2020

I will to check for cycle references here, marking as WIP for a bit.

Done.

envisage/extension_point.py Outdated Show resolved Hide resolved
envisage/extension_point.py Show resolved Hide resolved
envisage/plugin.py Outdated Show resolved Hide resolved
@kitchoi
Copy link
Contributor Author

kitchoi commented Nov 3, 2020

From offline discussion: The current plan for the next release of Envisage (current version is 4.9.2) is that it will still support Traits 6.0. With that this PR should remain on hold until after the next release.

Review is still very welcome though.

Copy link
Contributor

@rahulporuri rahulporuri left a comment

Choose a reason for hiding this comment

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

This LGTM but I would like to test this against internal apps which use envisage to confirm further.

Also, this is a substantial change and I think it might be good to put together a design document accompanying the changes. Do you think that's worth the time?

Comment on lines 359 to 363
warnings.warn(
"Extension point cannot be mutated directly.",
RuntimeWarning,
stacklevel=2,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

is it overkill to refactor all of the warnings into a common _raise_warnings method or something of that sort?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not an overkill at all... I should do that.

I think it might be good to put together a design document accompanying the changes.

I'd thought that extensive class docstring on _ExtensionPointValue was good enough to explain the rationale, the benefit compared to having a separate design document is that it is close to the code, and therefore it can describe concrete details that can be maintained together. A design document tends to stay high-level and more abstract. Is there any high-level rationale I missed there and does not sit well in the class or module docstring?

Copy link
Contributor

Choose a reason for hiding this comment

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

that makes sense too. i think class and module docstrings should be enough.

@kitchoi
Copy link
Contributor Author

kitchoi commented Nov 30, 2020

Refactored warning code and merged master in here. However the pickability on Python 3.7+ needs a bit more investigation.

@kitchoi
Copy link
Contributor Author

kitchoi commented Jan 6, 2021

Fixed un/pickling issue. Note that CI is not run against Python 3.7+. I ran the test locally with a venv from Python 3.9 and verified they pass.

@rahulporuri rahulporuri self-requested a review January 12, 2021 16:16
Copy link
Contributor

@rahulporuri rahulporuri left a comment

Choose a reason for hiding this comment

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

Changes LGTM. Spending a bit of time testing these changes with internal projects.

envisage/extension_point.py Outdated Show resolved Hide resolved
Co-authored-by: Poruri Sai Rahul <rporuri@enthought.com>
@rahulporuri
Copy link
Contributor

Tested against an internal application and things worked as expected. Still LGTM. I'll maybe spend a bit more time testing against one more internal application.

@rahulporuri
Copy link
Contributor

Caution: This implementation requires Traits 6.1, as it imports TraitList from traits.trait_list_object. We should decide if it is necessary to phase in Traits 6.1. Should it be decided that the next release of Envisage will still support Traits 6.0, some additional compatibility layer will be needed for this PR. Edited: but I don't think it would be much (We just need to roll the old ExtensionPoint definition for that, that's all.), or this PR can be considered for merging after next release.

I think the next release of envisage will depend on traits >= 6.2.0 so we don't need to worry about adding any additional compatibility layer.

@kitchoi
Copy link
Contributor Author

kitchoi commented Jan 13, 2021

I think the next release of envisage will depend on traits >= 6.2.0 so we don't need to worry about adding any additional compatibility layer.

I will update the setup.py to require traits>=6.1 so that the bump is tied to the change that requires it.

@kitchoi
Copy link
Contributor Author

kitchoi commented Jan 13, 2021

I will update the setup.py to require traits>=6.1 so that the bump is tied to the change that requires it.

Done. I believe the setup.py the only place that requires the bump, and I tested installation locally with pip successfully (CI does not have a job that uses pip install with the local source). I did not change etstool.py as the EDM tool is already pulling in the latest released version of traits, and if it did not, the test suite will fail so we will know about it.

@kitchoi
Copy link
Contributor Author

kitchoi commented Jan 14, 2021

Confirmed offline that this can be merged... merging...

@kitchoi kitchoi merged commit d62af08 into master Jan 14, 2021
@kitchoi kitchoi deleted the 291-extension-point-as-a-cached-immutable-list branch January 14, 2021 16:04
rahulporuri pushed a commit that referenced this pull request Jun 8, 2021
rahulporuri pushed a commit that referenced this pull request Jun 8, 2021
@rahulporuri rahulporuri mentioned this pull request Jun 8, 2021
rahulporuri pushed a commit that referenced this pull request Jun 11, 2021
@rahulporuri rahulporuri mentioned this pull request Jun 11, 2021
rahulporuri pushed a commit that referenced this pull request Jun 14, 2021
* Revert "Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] (#354)"

This reverts commit d62af08.

* TST/FIX : Revert test that used observe to listen to changes to

extension point items. The test now uses a static trait change handler
like before

	modified:   envisage/tests/test_plugin.py
rahulporuri pushed a commit that referenced this pull request Jun 17, 2021
* Revert "Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] (#354)"

This reverts commit d62af08.

* TST/FIX : Revert test that used observe to listen to changes to

extension point items. The test now uses a static trait change handler
like before

	modified:   envisage/tests/test_plugin.py
rahulporuri pushed a commit that referenced this pull request Jun 17, 2021
* Revert PR #354 (#422)

* Revert "Support observe("name:items") for ExtensionPoint [Requires Traits 6.1] (#354)"

This reverts commit d62af08.

* TST/FIX : Revert test that used observe to listen to changes to

extension point items. The test now uses a static trait change handler
like before

	modified:   envisage/tests/test_plugin.py

* Regression test for #417 (#421)

* Add failing test

* STY: Fix line spacing issues

Co-authored-by: Poruri Sai Rahul <rporuri@enthought.com>

* Fix test suite dependence on ipykernel (#423)

* Fix hard test suite dependence on ipykernel

* Update envisage/tests/test_ids.py

Co-authored-by: Poruri Sai Rahul <rporuri@enthought.com>

Co-authored-by: Poruri Sai Rahul <rporuri@enthought.com>

* DOC : Update changelog

	modified:   CHANGES.rst

Co-authored-by: Mark Dickinson <mdickinson@enthought.com>
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.

Support for observe in ExtensionPoint
2 participants