Source code for secsgem.common.callbacks

#####################################################################
# callback.py
#
# (c) Copyright 2016, Benjamin Parzella. All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#####################################################################
"""Contains callback handling routines."""

from __future__ import annotations

import typing


class _CallbackCallWrapper:
    def __init__(self, handler: CallbackHandler, name: str):
        self._name = name
        self._handler = handler

    def __call__(self, *args: tuple, **kwargs: dict) -> typing.Any:
        return self.handler._call(self.name, *args, **kwargs)  # noqa: SLF001

    @property
    def name(self) -> str:
        """Get the callback name."""
        return self._name

    @property
    def handler(self) -> CallbackHandler:
        """Get the handler for the callback."""
        return self._handler


[docs] class CallbackHandler: """Handler for callbacks for HSMS/SECS/GEM events. This handler manages callbacks for events that can happen on a handler for a connection. """ def __init__(self) -> None: """Initialize the handler.""" self._callbacks: dict[str, typing.Callable] = {} self.target: object = None self._object_intitialized = True def __setattr__(self, name: str, value: typing.Callable): """Set an item as object member. Args: name: name of the callback value: callback function """ if "_object_intitialized" not in self.__dict__ or name in self.__dict__: dict.__setattr__(self, name, value) return if value is None: if name in self._callbacks: del self._callbacks[name] else: self._callbacks[name] = value def __getattr__(self, name: str) -> typing.Callable: """Get a callable function for an event. Args: name: name of the event """ return _CallbackCallWrapper(self, name) class _CallbacksIter: def __init__(self, keys): self._keys = list(keys) self._counter = 0 def __iter__(self): return self def __next__(self): if self._counter < len(self._keys): i = self._counter self._counter += 1 return self._keys[i] raise StopIteration def __iter__(self) -> _CallbacksIter: """Get an iterator for the callbacks. Returns: callback iterator """ return self._CallbacksIter(self._callbacks.keys()) def __contains__(self, callback: str) -> bool: """Check if a callback is present. Args: callback: name of the event Returns: True if callback present """ if callback in self._callbacks: return True delegate_handler = getattr(self.target, "_on_" + callback, None) return bool(callable(delegate_handler)) def _call(self, callback: str, *args, **kwargs) -> typing.Any: if callback in self._callbacks: return self._callbacks[callback](*args, **kwargs) delegate_handler = getattr(self.target, "_on_" + callback, None) if callable(delegate_handler): return delegate_handler(*args, **kwargs) return None