from functools import wraps, partial from PyQt6.QtCore import pyqtSignal, pyqtSlot from electrum.logging import get_logger def auth_protect(func=None, reject=None, method='pin', message=''): if func is None: return partial(auth_protect, reject=reject, method=method, message=message) @wraps(func) def wrapper(self, *args, **kwargs): _logger = get_logger(__name__) _logger.debug(f'{str(self)}.{func.__name__}') if hasattr(self, '__auth_fcall'): _logger.debug('object already has a pending authed function call') raise Exception('object already has a pending authed function call') setattr(self, '__auth_fcall', (func, args, kwargs, reject)) getattr(self, 'authRequired').emit(method, message) return wrapper class AuthMixin: _auth_logger = get_logger(__name__) authRequired = pyqtSignal([str, str], arguments=['method', 'authMessage']) @pyqtSlot() def authProceed(self): self._auth_logger.debug('Proceeding with authed fn()') try: self._auth_logger.debug(str(getattr(self, '__auth_fcall'))) (func, args, kwargs, reject) = getattr(self, '__auth_fcall') r = func(self, *args, **kwargs) return r except Exception as e: self._auth_logger.error(f'Error executing wrapped fn(): {repr(e)}') raise e finally: delattr(self, '__auth_fcall') @pyqtSlot() def authCancel(self): self._auth_logger.debug('Cancelling authed fn()') if not hasattr(self, '__auth_fcall'): return try: (func, args, kwargs, reject) = getattr(self, '__auth_fcall') if reject is not None: if hasattr(self, reject): getattr(self, reject)() else: self._auth_logger.error(f'Reject method "{reject}" not defined') except Exception as e: self._auth_logger.error(f'Error executing reject function "{reject}": {repr(e)}') raise e finally: delattr(self, '__auth_fcall')