def vars(cls): """Like the built-in function `vars`, but also works with slotted classes""" if not hasattr(cls, "__slots__"): return _vars_(cls) allVars = OrderedSet() for cls in cls.__mro__: for varName in getattr(cls, "__slots__", tuple()): allVars.add(varName) return allVars
class EventProxy(EventReceiver): """ Any method called on this class (besides reserved functions declared in this class) will be proxied out to all EventReceivers registered with the class. This class is also an EventReceiver itself, as it receives events. Therefore, multiple EventProxy's can be tied together; an event proxy can be registered as an EventReceiver with another EventProxy. """ def __init__(self, errorOnMethodNotFound): """ @param errorOnMethodNotFound bool: If `True`, it is an error when a receiver doesn't implement a method. If `False`, that receiver is simply skipped. Note that if the special method `notifyException` is not implemented, no error will be raised from this class. """ self.errorOnMethodNotFound = errorOnMethodNotFound self._receivers = OrderedSet() self._tieInExceptHook() def _tieInExceptHook(self): oldFunc = sys.excepthook def branchHook(exceptionClass, exceptionInstance, tracebackInstance): oldFunc(exceptionClass, exceptionInstance, tracebackInstance) self.notifyException(exceptionInstance, tracebackInstance) sys.excepthook = branchHook def __getattr__(self, name): # __getattr__ (instead of __getattribute__) won't work because it doesn't work with super # if hasattr(super(EventProxy, self), name): # return super(EventProxy, self).__getattribute__(name) # if name in self.__dict__: # return self.__dict__ def _run(*args, **kwargs): found = False for receiver in self._receivers: if hasattr(receiver, name): found = True getattr(receiver, name)(*args, **kwargs) if not found: if name != "notifyException" and self.errorOnMethodNotFound: raise AttributeError return _run def addReceiver(self, receiver, errorOnDuplicate=True): if self._receivers.add(receiver, updateOnExist=False) == False and errorOnDuplicate: raise Exception("Event receiver already added") def getReceivers(self): return self._receivers