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

PERF: delay preset sync until tab completion is accessed #1317

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
43 changes: 28 additions & 15 deletions pcdsdevices/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -899,25 +904,29 @@ 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.

Sets the paths for saving and loading presets.

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:
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down