Source code for jdaviz.core.registries

import re

from glue.config import DictRegistry
from ipyvuetify import VuetifyTemplate
from ipywidgets import Widget


__all__ = ['convert', 'UniqueDictRegistry', 'ViewerRegistry', 'TrayRegistry',
           'ToolRegistry', 'MenuRegistry', 'DataParserRegistry',
           'viewer_registry', 'tray_registry', 'tool_registry', 'menu_registry',
           'data_parser_registry']


def _to_snake(s):
    """Convert dashes in viewer category names to underscores for
    use in class attributes, constructor kwargs, requirement kwargs.
    """
    return s.replace("-", "_")


[docs] def convert(name): """Converts camel-case strings to snake-case. Used when a user does not define a specific name for a registry item. Returns ------- val : str Name converted to snake-case. """ s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
[docs] class UniqueDictRegistry(DictRegistry): """Base registry class that handles hashmap-like associations between a string representation of a plugin and the class to be instantiated. """
[docs] def add(self, name, cls, overwrite=False): """Add an item to the registry. Parameters ---------- name : str The name referencing the associated class in the registry. cls : type The class definition (not instance) associated with the name given in the first parameter. overwrite : bool, optional Whether to overwrite an existing entry with the same ``label``. """ if name in self.members and not overwrite: raise ValueError(f"Viewer with the name {name} already exists, " f"please choose a different name or pass overwrite=True.") else: self.members[name] = cls
[docs] class ViewerRegistry(UniqueDictRegistry): """Registry containing references to custom viewers."""
[docs] def __call__(self, name=None, label=None, overwrite=False): def decorator(cls): self.add(name, cls, label, overwrite=overwrite) return cls return decorator
[docs] def add(self, name, cls, label=None, overwrite=False): """Add an item to the registry. Parameters ---------- name : str The key referencing the associated class in the registry dictionary. cls : type The class definition (not instance) associated with the name given in the first parameter. label : str, optional The label displayed in the tooltip when hovering over the tray tab. overwrite : bool, optional Whether to overwrite an existing entry with the same ``label``. """ if name in self.members and not overwrite: raise ValueError(f"Viewer with the name {name} already exists, " f"please choose a different name or pass overwrite=True.") else: self.members[name] = {'label': label, 'cls': cls}
[docs] class TrayRegistry(UniqueDictRegistry): """Registry containing references to plugins that will be added to the sidebar tray tabs. """ default_viewer_category = [ "spectrum", "table", "image", "spectrum-2d", "flux", "uncert" ] default_viewer_reqs = { category: { "cls_attr": f"_default_{_to_snake(category)}_viewer_reference_name", "init_kwarg": f"{_to_snake(category)}_viewer_reference_name", "require_kwargs": [f"require_{_to_snake(category)}_viewer"] } for category in default_viewer_category }
[docs] def __call__(self, name=None, label=None, icon=None, viewer_requirements=[], overwrite=False): def decorator(cls): # The class must inherit from `VuetifyTemplate` in order to be # ingestible by the component initialization. if not issubclass(cls, VuetifyTemplate): raise ValueError( f"Unrecognized superclass for {cls.__name__}. All " f"registered components must inherit from " f"`ipyvuetify.VuetifyTemplate`.") self.add(name, cls, label, icon, viewer_requirements, overwrite) return cls return decorator
[docs] def add(self, name, cls, label=None, icon=None, viewer_requirements=[], overwrite=False): """Add an item to the registry. Parameters ---------- name : str The key referencing the associated class in the registry dictionary. cls : type The class definition (not instance) associated with the name given in the first parameter. label : str, optional The label displayed in the tooltip when hovering over the tray tab. icon : str, optional The name of the icon to render in the tray tab. viewer_requirements : str, list of str Required viewers for this plugin. overwrite : bool, optional Whether to overwrite an existing entry with the same ``label``. """ if name in self.members and not overwrite: raise ValueError(f"Viewer with the name {name} already exists, " f"please choose a different name or pass overwrite=True.") else: # store the registry name/label so we can access them from the instantiated # objects (when determining if a specific plugin is open, for example) viewer_reference_name_kwargs = {} if not isinstance(viewer_requirements, list): viewer_requirements = [viewer_requirements] for category in viewer_requirements: if category not in self.default_viewer_reqs: raise ValueError(f'Viewer requirements not defined ' f'for viewer category: "{category}" ' f'in plugin "{cls.__class__.__name__}".') req = self.default_viewer_reqs[category] viewer_cls_attr = req['cls_attr'] viewer_specific_kwarg = req['init_kwarg'] requirements = req['require_kwargs'] viewer_reference_name_kwargs[viewer_cls_attr] = [ viewer_specific_kwarg, { k: True for k in requirements } ] cls._registry_name = name cls._registry_label = label self.members[name] = {'label': label, 'icon': icon, 'cls': cls, 'viewer_reference_name_kwargs': viewer_reference_name_kwargs}
[docs] class ToolRegistry(UniqueDictRegistry): """Registry containing references to plugins which will populate the application-level toolbar. """
[docs] def __call__(self, name=None, overwrite=False): def decorator(cls): # The class must inherit from `Widget` in order to be # ingestible by the component initialization. if not issubclass(cls, Widget): raise ValueError( f"Unrecognized superclass for `{cls.__name__}`. All " f"registered tools must inherit from " f"`ipywidgets.Widget`.") self.add(name, cls, overwrite) return cls return decorator
[docs] class DataParserRegistry(UniqueDictRegistry): """Registry containing parsing functions for attempting to auto-populate the application-defined initial viewers. """
[docs] def __call__(self, name=None): def decorator(func): self.add(name, func) return func return decorator
viewer_registry = ViewerRegistry() tray_registry = TrayRegistry() tool_registry = ToolRegistry() menu_registry = MenuRegistry() data_parser_registry = DataParserRegistry()