diff --git a/CHANGES.rst b/CHANGES.rst index 98530b8442..66ac49595f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,11 +4,13 @@ New Features ------------ -- Adding flux/surface brightness translation and surface brightness +- Added flux/surface brightness translation and surface brightness unit conversion in Cubeviz and Specviz. [#2781] - Plugin tray is now open by default. [#2892] +- New "About" plugin to show Jdaviz version info. [#2886] + Cubeviz ^^^^^^^ diff --git a/docs/reference/api_plugins.rst b/docs/reference/api_plugins.rst index c7ee208e22..185b1a652a 100644 --- a/docs/reference/api_plugins.rst +++ b/docs/reference/api_plugins.rst @@ -3,6 +3,9 @@ Plugins API =========== +.. automodapi:: jdaviz.configs.default.plugins.about.about + :no-inheritance-diagram: + .. automodapi:: jdaviz.configs.default.plugins.collapse.collapse :no-inheritance-diagram: diff --git a/jdaviz/configs/cubeviz/cubeviz.yaml b/jdaviz/configs/cubeviz/cubeviz.yaml index f5da2d27a9..038df00431 100644 --- a/jdaviz/configs/cubeviz/cubeviz.yaml +++ b/jdaviz/configs/cubeviz/cubeviz.yaml @@ -34,6 +34,7 @@ tray: - cubeviz-moment-maps - imviz-aper-phot-simple - export + - about viewer_area: - container: col children: diff --git a/jdaviz/configs/default/default.yaml b/jdaviz/configs/default/default.yaml index ebf9e8449f..1c46ad2dc4 100644 --- a/jdaviz/configs/default/default.yaml +++ b/jdaviz/configs/default/default.yaml @@ -15,4 +15,5 @@ toolbar: tray: - g-subset-plugin - g-gaussian-smooth - - export \ No newline at end of file + - export + - about diff --git a/jdaviz/configs/default/plugins/__init__.py b/jdaviz/configs/default/plugins/__init__.py index a79315363a..a23c5b3cdc 100644 --- a/jdaviz/configs/default/plugins/__init__.py +++ b/jdaviz/configs/default/plugins/__init__.py @@ -12,3 +12,4 @@ from .plot_options.plot_options import * # noqa from .markers.markers import * # noqa from .data_quality.data_quality import * # noqa +from .about.about import * # noqa diff --git a/jdaviz/configs/default/plugins/about/__init__.py b/jdaviz/configs/default/plugins/about/__init__.py new file mode 100644 index 0000000000..53e66bf928 --- /dev/null +++ b/jdaviz/configs/default/plugins/about/__init__.py @@ -0,0 +1 @@ +from .about import * # noqa diff --git a/jdaviz/configs/default/plugins/about/about.py b/jdaviz/configs/default/plugins/about/about.py new file mode 100644 index 0000000000..6c9f0a8675 --- /dev/null +++ b/jdaviz/configs/default/plugins/about/about.py @@ -0,0 +1,56 @@ +import json + +import requests +from packaging.version import Version +from traitlets import Bool, Unicode + +from jdaviz.core.registries import tray_registry +from jdaviz.core.template_mixin import PluginTemplateMixin + +try: + from jdaviz import __version__ +except ImportError: # pragma: no cover + __version__ = "unknown" + +__all__ = ['About'] + + +@tray_registry('about', label="About") +class About(PluginTemplateMixin): + """Show information about Jdaviz.""" + template_file = __file__, "about.vue" + + jdaviz_version = Unicode("unknown").tag(sync=True) + jdaviz_pypi = Unicode("unknown").tag(sync=True) + not_is_latest = Bool(False).tag(sync=True) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.jdaviz_version = __version__ + + if __version__ != "unknown": + _ver_pypi = latest_version_from_pypi("jdaviz") + if _ver_pypi: + self.jdaviz_pypi = _ver_pypi + self.not_is_latest = Version(__version__) < Version(_ver_pypi) + else: # pragma: no cover + self.jdaviz_pypi = "unknown" + self.not_is_latest = False + + +def latest_version_from_pypi(package_name): + """Version info for given package or `None`.""" + url = f"https://pypi.org/pypi/{package_name}/json" + try: + r = requests.get(url, timeout=60) + except Exception: # nosec # pragma: no cover + pass + else: + if r.ok: + try: + d = json.loads(r.text) + v = d["info"]["version"] + except Exception: # nosec # pragma: no cover + pass + else: + return v diff --git a/jdaviz/configs/default/plugins/about/about.vue b/jdaviz/configs/default/plugins/about/about.vue new file mode 100644 index 0000000000..c5b477f140 --- /dev/null +++ b/jdaviz/configs/default/plugins/about/about.vue @@ -0,0 +1,42 @@ + diff --git a/jdaviz/configs/default/plugins/about/tests/__init__.py b/jdaviz/configs/default/plugins/about/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jdaviz/configs/default/plugins/about/tests/test_about_plugin.py b/jdaviz/configs/default/plugins/about/tests/test_about_plugin.py new file mode 100644 index 0000000000..5a10d25ade --- /dev/null +++ b/jdaviz/configs/default/plugins/about/tests/test_about_plugin.py @@ -0,0 +1,30 @@ +import pytest + +from jdaviz import __version__ +from jdaviz.configs.default.plugins.about.about import latest_version_from_pypi + + +@pytest.mark.remote_data +def test_get_latest_version_from_pypi(): + # Since the latest version will change over time, + # we can only check that something is returned but not what exactly. + + v = latest_version_from_pypi("jdaviz") + assert isinstance(v, str) + + v = latest_version_from_pypi("fakespacetelescopepackage") + assert v is None + + +# NOTE: Theoretically now all the tests in jdaviz are remote data tests +# because all the viz loads About plugin and About plugin always polls +# PyPI for the latest release version. If that bothers you or PyPI +# starts blocking us as spammer, we can consider caching it at package level +# but that introduces new non-standard package attributes. +def test_about_basic(specviz_helper): + plg = specviz_helper.plugins["About"]._obj + + assert plg.jdaviz_version == __version__ + assert isinstance(plg.jdaviz_pypi, str) + # not_is_latest can be non-deterministic because user can be running + # this test from an older version going forward, so we skip checking it. diff --git a/jdaviz/configs/imviz/imviz.yaml b/jdaviz/configs/imviz/imviz.yaml index dd5ded7d00..9f0c49732a 100644 --- a/jdaviz/configs/imviz/imviz.yaml +++ b/jdaviz/configs/imviz/imviz.yaml @@ -31,6 +31,7 @@ tray: - imviz-catalogs - imviz-footprints - export + - about viewer_area: - container: col children: diff --git a/jdaviz/configs/mosviz/mosviz.yaml b/jdaviz/configs/mosviz/mosviz.yaml index 6f4f877912..220e6d2cc0 100644 --- a/jdaviz/configs/mosviz/mosviz.yaml +++ b/jdaviz/configs/mosviz/mosviz.yaml @@ -26,6 +26,7 @@ tray: - g-line-list - specviz-line-analysis - export + - about viewer_area: - container: col children: diff --git a/jdaviz/configs/specviz/specviz.yaml b/jdaviz/configs/specviz/specviz.yaml index 92442c07f8..4eff5edf94 100644 --- a/jdaviz/configs/specviz/specviz.yaml +++ b/jdaviz/configs/specviz/specviz.yaml @@ -27,6 +27,7 @@ tray: - g-line-list - specviz-line-analysis - export + - about viewer_area: - container: col children: diff --git a/jdaviz/configs/specviz2d/specviz2d.yaml b/jdaviz/configs/specviz2d/specviz2d.yaml index e1c0206435..ec7b36c212 100644 --- a/jdaviz/configs/specviz2d/specviz2d.yaml +++ b/jdaviz/configs/specviz2d/specviz2d.yaml @@ -25,6 +25,7 @@ tray: - g-line-list - specviz-line-analysis - export + - about viewer_area: - container: col children: diff --git a/pyproject.toml b/pyproject.toml index 3647ced0e4..a3744e4301 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ dependencies = [ "sidecar>=0.5.2", "ipypopout>=0.0.11", "astroquery", + "requests", ] dynamic = [ "version",