diff --git a/pcdsdevices/interface.py b/pcdsdevices/interface.py index a139fdd4669..f8d7f3962b8 100644 --- a/pcdsdevices/interface.py +++ b/pcdsdevices/interface.py @@ -227,8 +227,13 @@ def __init_subclass__(cls, **kwargs): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._tab = self._class_tab.new_instance(self) + self._tab_initialized = False def __dir__(self): + if not self._tab_initialized and hasattr(self, 'presets'): + self._tab_initialized = True + self.presets.sync() + return self._tab.get_dir() def __repr__(self): @@ -899,7 +904,7 @@ def set_position(self, position): self.set_current_position(position) -def setup_preset_paths(**paths): +def setup_preset_paths(**kwargs): """ Prepare the :class:`Presets` class. @@ -907,17 +912,21 @@ def setup_preset_paths(**paths): Parameters ---------- - **paths : str keyword args + **kwargs: str keyword args A mapping from type of preset to destination path. These will be directories that contain the yaml files that define the preset positions. - """ + (Optional) "defer_loading": bool, whether or not to defer the loading + of preset files until the first tab completion + """ + defer_loading = kwargs.pop("defer_loading", False) + paths = kwargs Presets._paths = {} for k, v in paths.items(): Presets._paths[k] = Path(v) for preset in Presets._registry: - preset.sync() + preset.sync(defer_loading=defer_loading) class Presets: @@ -1079,22 +1088,25 @@ def _update(self, preset_type, name, value=None, comment=None, except BlockingIOError: self._log_flock_error() - def sync(self): + def sync(self, defer_loading: bool = False): """Synchronize the presets with the database.""" logger.debug('call %s presets.sync()', self._device.name) self._remove_methods() self._cache = {} logger.debug('filling %s cache', self.name) - for preset_type in self._paths.keys(): - path = self._path(preset_type) - if path.exists(): - try: - self._cache[preset_type] = self._read(preset_type) - except BlockingIOError: - self._log_flock_error() - else: - logger.debug('No %s preset file for %s', - preset_type, self._device.name) + + # only consult files if requested + if not defer_loading: + for preset_type in self._paths.keys(): + path = self._path(preset_type) + if path.exists(): + try: + self._cache[preset_type] = self._read(preset_type) + except BlockingIOError: + self._log_flock_error() + else: + logger.debug('No %s preset file for %s', + preset_type, self._device.name) self._create_methods() def _log_flock_error(self): @@ -1140,6 +1152,7 @@ def _register_method(self, obj, method_name, method): self._methods.append((obj, method_name)) setattr(obj, method_name, MethodType(method, obj)) if hasattr(obj, '_tab'): + # obj._tab: TabCompletionHelperInstance obj._tab.add(method_name) def _make_add(self, preset_type):