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

Plugin user API: inapplicable attrs #2347

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Specviz2d
API Changes
-----------

- Plugin user APIs now hide attributes that are not applicable based on the values of other options
within the plugin. [#2347]

Cubeviz
^^^^^^^

Expand Down
14 changes: 13 additions & 1 deletion jdaviz/configs/imviz/plugins/links_control/links_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ class LinksControl(PluginTemplateMixin):
* :meth:`~jdaviz.core.template_mixin.PluginTemplateMixin.close_in_tray`
* ``link_type`` (`~jdaviz.core.template_mixin.SelectPluginComponent`)
* ``wcs_use_affine``
Only applicable if ``link_type`` is 'WCS'
"""
template_file = __file__, "links_control.vue"
inapplicable_attrs = List().tag(sync=True)

link_type_items = List().tag(sync=True)
link_type_selected = Unicode().tag(sync=True)
Expand Down Expand Up @@ -62,9 +64,18 @@ def __init__(self, *args, **kwargs):
self.hub.subscribe(self, MarkersChangedMessage,
handler=self._on_markers_changed)

self._update_inapplicable_attrs()

@property
def user_api(self):
return PluginUserApi(self, expose=('link_type', 'wcs_use_affine'))
return PluginUserApi(self, expose=('link_type', 'wcs_use_affine'),
inapplicable_attrs='inapplicable_attrs')

def _update_inapplicable_attrs(self):
if self.link_type.selected == 'Pixels':
self.inapplicable_attrs = ['wcs_use_affine']
else:
self.inapplicable_attrs = []

def _on_link_updated(self, msg):
self.link_type.selected = {'pixels': 'Pixels', 'wcs': 'WCS'}[msg.link_type]
Expand Down Expand Up @@ -126,6 +137,7 @@ def _update_link(self, msg={}):
# reset wcs_use_affine to be True
self.wcs_use_affine = True

self._update_inapplicable_attrs()
self._link_image_data()

self.linking_in_progress = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</v-switch>
</v-row>

<v-row v-if="link_type_selected == 'WCS'">
<v-row v-if="!inapplicable_attrs.includes('wcs_use_affine')">
<v-switch
label="Fast approximation"
hint="Use fast approximation for image alignment if possible (accurate to <1 pixel)."
Expand Down
10 changes: 10 additions & 0 deletions jdaviz/configs/imviz/tests/test_links_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,13 @@ def test_plugin(self):

assert lc_plugin.need_clear_markers is False
lc_plugin.link_type.selected = 'WCS'

def test_user_api(self):
lc_plugin = self.imviz.plugins['Links Control']
assert lc_plugin.link_type == 'Pixels'
# wcs_use_affine is inapplicable when link_type == 'Pixels'
with pytest.raises(AttributeError):
lc_plugin.wcs_use_affine

lc_plugin.link_type = 'WCS'
assert lc_plugin.wcs_use_affine is True
17 changes: 13 additions & 4 deletions jdaviz/core/user_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

__all__ = ['UserApiWrapper', 'PluginUserApi', 'ViewerUserApi']

_internal_attrs = ('_obj', '_expose', '_readonly', '__doc__')
_internal_attrs = ('_obj', '_expose', '_readonly', '_inapplicable_attrs', '__doc__')


class UserApiWrapper:
"""
This is an API wrapper around an internal object. For a full list of attributes/methods,
call dir(object).
"""
def __init__(self, obj, expose=[], readonly=[]):
def __init__(self, obj, expose=[], readonly=[], inapplicable_attrs=None):
self._obj = obj
self._expose = list(expose) + list(readonly)
self._readonly = readonly
self._inapplicable_attrs = inapplicable_attrs # string of a traitlet in obj or None
if obj.__doc__ is not None:
self.__doc__ = self.__doc__ + "\n\n\n" + obj.__doc__

Expand All @@ -30,6 +31,10 @@
if attr in _internal_attrs or attr not in self._expose:
return super().__getattribute__(attr)

if self._inapplicable_attrs is not None:
if attr in getattr(self._obj, self._inapplicable_attrs):
raise AttributeError(f"{attr} is not currently applicable due to values of other parameters") # noqa

exp_obj = getattr(self._obj, attr)
return getattr(exp_obj, 'user_api', exp_obj)

Expand All @@ -39,6 +44,10 @@
if attr not in self._expose:
raise ValueError(f"{attr} is not a valid attribute and cannot be set")

if self._inapplicable_attrs is not None:
if attr in getattr(self._obj, self._inapplicable_attrs):
raise AttributeError(f"{attr} is not currently applicable due to values of other parameters") # noqa

Check warning on line 49 in jdaviz/core/user_api.py

View check run for this annotation

Codecov / codecov/patch

jdaviz/core/user_api.py#L49

Added line #L49 was not covered by tests

if attr in self._readonly:
raise AttributeError("cannot set read-only item")

Expand Down Expand Up @@ -90,11 +99,11 @@
For example::
help(plugin_object.show)
"""
def __init__(self, plugin, expose=[], readonly=[]):
def __init__(self, plugin, expose=[], readonly=[], inapplicable_attrs=None):
expose = list(set(list(expose) + ['open_in_tray', 'close_in_tray', 'show']))
if plugin.uses_active_status:
expose += ['keep_active', 'as_active']
super().__init__(plugin, expose, readonly)
super().__init__(plugin, expose, readonly, inapplicable_attrs)

def __repr__(self):
return f'<{self._obj._registry_label} API>'
Expand Down
Loading