From 7d8f45b9fe9d29c9807233067d1037a7dfcf4f92 Mon Sep 17 00:00:00 2001 From: Jared Suttles Date: Wed, 3 Jun 2020 15:32:17 -0400 Subject: [PATCH 1/3] add event hooks --- rumps/_internal.py | 6 +++--- rumps/notifications.py | 15 +++++---------- rumps/rumps.py | 20 ++++++++++++-------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/rumps/_internal.py b/rumps/_internal.py index a04ae7c..a4d5320 100644 --- a/rumps/_internal.py +++ b/rumps/_internal.py @@ -27,7 +27,7 @@ def require_string_or_none(*objs): ) -def call_as_function_or_method(func, event): +def call_as_function_or_method(func, *args, **kwargs): # The idea here is that when using decorators in a class, the functions passed are not bound so we have to # determine later if the functions we have (those saved as callbacks) for particular events need to be passed # 'self'. @@ -42,8 +42,8 @@ def call_as_function_or_method(func, event): else: for name, method in inspect.getmembers(app, predicate=inspect.ismethod): if method.__func__ is func: - return method(event) - return func(event) + return method(*args, **kwargs) + return func(*args, **kwargs) def guard_unexpected_errors(func): diff --git a/rumps/notifications.py b/rumps/notifications.py index 08d048b..64c61cd 100644 --- a/rumps/notifications.py +++ b/rumps/notifications.py @@ -15,6 +15,7 @@ from . import _internal from . import compat +from . import events def on_notification(f): @@ -32,8 +33,7 @@ def notification_center(info): print 'i know this' """ - on_notification.__dict__['*'] = f - return f + return events.on_notification.register(f) def _gather_info_issue_9(): # pragma: no cover @@ -116,20 +116,15 @@ def _clicked(ns_user_notification_center, ns_user_notification): traceback.print_exc() return - try: - notification_handler = getattr(on_notification, '*') - except AttributeError: - # notification center function not specified, no error but log warning + # notification center function not specified => no error but log warning + if not events.on_notification.callbacks: rumps._log( 'WARNING: notification received but no function specified for ' 'answering it; use @notifications decorator to register a function.' ) else: notification = Notification(ns_user_notification, data) - try: - _internal.call_as_function_or_method(notification_handler, notification) - except Exception: - traceback.print_exc() + events.on_notification.emit(notification) def notify(title, subtitle, message, data=None, sound=True, diff --git a/rumps/rumps.py b/rumps/rumps.py index d8f8404..9fcca31 100644 --- a/rumps/rumps.py +++ b/rumps/rumps.py @@ -24,6 +24,7 @@ from .compat import text_type, string_types, iteritems, collections_abc from . import _internal +from . import events from . import notifications _TIMERS = weakref.WeakKeyDictionary() @@ -948,15 +949,17 @@ def applicationDidFinishLaunching_(self, notification): None ) - def receiveSleepNotification_(self, notification): - _log("receiveSleepNotification") - app = getattr(App, '*app_instance') - return app.sleep() + def receiveSleepNotification_(self, ns_notification): + _log('receiveSleepNotification') + events.on_sleep.emit() - def receiveWakeNotification_(self, notification): - _log("receiveWakeNotification") - app = getattr(App, '*app_instance') - return app.wake() + def receiveWakeNotification_(self, ns_notification): + _log('receiveWakeNotification') + events.on_wake.emit() + + def applicationWillTerminate_(self, ns_notification): + _log('applicationWillTerminate') + events.before_quit.emit() @classmethod def callback_(cls, nsmenuitem): @@ -1166,4 +1169,5 @@ def run(self, **options): self._nsapp.initializeStatusBar() AppHelper.installMachInterrupt() + events.before_start.emit() AppHelper.runEventLoop() From 68220d1b4348340d22fae01da1cfce3fa2b4a30d Mon Sep 17 00:00:00 2001 From: Jared Suttles Date: Wed, 3 Jun 2020 15:38:33 -0400 Subject: [PATCH 2/3] include events module --- rumps/events.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 rumps/events.py diff --git a/rumps/events.py b/rumps/events.py new file mode 100644 index 0000000..64f4439 --- /dev/null +++ b/rumps/events.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +import traceback + +from . import _internal + + +class EventEmitter(object): + def __init__(self, name): + self.name = name + self.callbacks = set() + self._executor = _internal.call_as_function_or_method + + def register(self, func): + self.callbacks.add(func) + return func + + def unregister(self, func): + try: + self.callbacks.remove(func) + return True + except KeyError: + return False + + def emit(self, *args, **kwargs): + #print('EventEmitter("%s").emit called' % self.name) + for callback in self.callbacks: + try: + self._executor(callback, *args, **kwargs) + except Exception: + traceback.print_exc() + + __call__ = register + + +before_start = EventEmitter('before_start') +on_notification = EventEmitter('on_notification') +on_sleep = EventEmitter('on_sleep') +on_wake = EventEmitter('on_wake') +before_quit = EventEmitter('before_quit') From a174d1669c975cec06fc941f982c6e53918132b0 Mon Sep 17 00:00:00 2001 From: Jared Suttles Date: Mon, 5 Jul 2021 07:57:27 -0400 Subject: [PATCH 3/3] update CHANGES 140 --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 941ab8b..d249804 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Changes 0.3.0.dev --------- +- Add event hooks, enable multiple event handlers #140 - Allow menu items to be hidden #138 - Fix dark mode alert style #137 - Notifications: fixes, cleanup, and tests #131