From f6ad0527a633f171b9ac897774f4cdb33528f69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 09:49:57 +0200 Subject: [PATCH 1/7] notify-send +general improvements --- notifypy/notify.py | 31 +++++-- notifypy/os_notifiers/linux.py | 148 ++++++++------------------------- 2 files changed, 59 insertions(+), 120 deletions(-) diff --git a/notifypy/notify.py b/notifypy/notify.py index 7277535..c82a2eb 100644 --- a/notifypy/notify.py +++ b/notifypy/notify.py @@ -23,6 +23,7 @@ def __init__( default_notification_title="Default Title", default_notification_message="Default Message", default_notification_application_name="Python Application (notify.py)", + default_notification_urgency='normal', default_notification_icon=None, default_notification_audio=None, enable_logging=False, @@ -74,6 +75,7 @@ def __init__( self._notification_title = default_notification_title self._notification_message = default_notification_message self._notification_application_name = default_notification_application_name + self._notification_urgency = default_notification_urgency # These defaults require verification if default_notification_icon: @@ -111,16 +113,17 @@ def _selected_notification_system( return LinuxNotifierLibNotify else: - from .os_notifiers.linux import USE_LEGACY + from .os_notifiers.linux import NOTIFY - if USE_LEGACY == False: + if NOTIFY: + from .os_notifiers.linux import LinuxNotifierLibNotify + + return LinuxNotifierLibNotify + else: from .os_notifiers.linux import LinuxNotifier return LinuxNotifier - else: - from .os_notifiers.linux import LinuxNotifierLibNotify - return LinuxNotifierLibNotify elif selected_platform == "Darwin": from .os_notifiers.macos import MacOSNotifier @@ -250,6 +253,20 @@ def application_name(self): def application_name(self, new_application_name): self._notification_application_name = new_application_name + @property + def urgency(self): + """The urgency of the notification (low, normal, critical) + Work only with libnotify (Linux), as of now + + Returns: + str: The urgency of the notification. + """ + return self._notification_urgency + + @urgency.setter + def urgency(self, new_urgency): + self._notification_urgency = new_urgency + def send(self, block=True): """Main send function. This will take all attributes sent and forward to send_notification. @@ -288,6 +305,7 @@ def start_notification_thread(self, event): supplied_title=self._notification_title, supplied_message=self._notification_message, supplied_application_name=self._notification_application_name, + supplied_urgency=self._notification_urgency, supplied_icon_path=self._notification_icon, supplied_audio_path=self._notification_audio, ) @@ -301,6 +319,7 @@ def send_notification( supplied_title, supplied_message, supplied_application_name, + supplied_urgency, supplied_icon_path, supplied_audio_path, ): @@ -310,6 +329,7 @@ def send_notification( supplied_title str: Title for notification supplied_message str: Message for notification supplied_application_name str: Application name for notification (if platform needs it) + supplied_urgency str: low, normal, critical | Notification urgency supplied_icon_path str: Direct path to custom icon supplied_audio_path str: Direct path to custom audio @@ -324,6 +344,7 @@ def send_notification( notification_title=str(supplied_title), notification_subtitle=str(supplied_message), application_name=str(supplied_application_name), + notification_urgency=str(supplied_urgency), notification_icon=str(supplied_icon_path), notification_audio=str(supplied_audio_path) if supplied_audio_path diff --git a/notifypy/os_notifiers/linux.py b/notifypy/os_notifiers/linux.py index ee89216..9144d22 100644 --- a/notifypy/os_notifiers/linux.py +++ b/notifypy/os_notifiers/linux.py @@ -2,81 +2,43 @@ import subprocess import shlex -from ..exceptions import BinaryNotFound, NotificationFailure, LinuxDbusException +from ..exceptions import BinaryNotFound from ._base import BaseNotifier try: from jeepney import DBusAddress, new_method_call from jeepney.io.blocking import open_dbus_connection - import os - - # check if dbus is available - _dbus_address = os.getenv("DBUS_SESSION_BUS_ADDRESS") - if _dbus_address: - logger.info("Jeepney and Dbus is available. Using DBUS for notifications..") - USE_LEGACY = False - else: - logger.error( - "Jeepney is available but DBUS is not. Using legacy notification instead." - ) - USE_LEGACY = True -except ImportError: - logger.error("DBUS suppport not installed. Using libnotify for notifications!") - USE_LEGACY = True + from shutil import which + NOTIFY = which('notify-send') # alternatively: from ctypes.util import find_library -class LinuxNotifierLibNotify(BaseNotifier): - def __init__(self): - """Main Linux Notification Class + if NOTIFY: + logger.info("libnotify found, using it for notifications") + else: # check if dbus is available + import os + _dbus_address = os.getenv("DBUS_SESSION_BUS_ADDRESS") + if _dbus_address: + logger.info("Jeepney and Dbus is available. Using DBUS for notifications..") + else: + raise ImportError - This uses libnotify's tool of notfiy-send. - I'll add support for (and probably use as first choice) sending - through dbus. + APLAY = which('aplay') - """ + if APLAY == None: + logger.debug("aplay binary not installed.. audio will not work!") - call_find_notify_send = self._find_installed_notify_send() - if not call_find_notify_send: - logger.error("Unable to find notify-send.") - raise BinaryNotFound("notify-send") - if call_find_notify_send: - self._notify_send_binary = call_find_notify_send +except ImportError: + logger.error("libnotify nor DBUS installed.") - call_find_aplay = self._find_installed_aplay() - if not call_find_aplay: - # no Aplay is available. - self._aplay_binary = False - else: - self._aplay_binary = call_find_aplay - @staticmethod - def _find_installed_aplay(): - """Function to find the path for notify-send""" - try: - run_which_for_aplay = subprocess.check_output(["which", "aplay"]) - return run_which_for_aplay.decode("utf-8") - except subprocess.CalledProcessError: - logger.exception("Unable to find aplay.") - return False - except Exception: - logger.exception("Unhandled exception for finding aplay.") - return False +class LinuxNotifierLibNotify(BaseNotifier): + def __init__(self): + """Main Linux Notification Class - @staticmethod - def _find_installed_notify_send(): - """Function to find the path for notify-send""" - try: - run_which_for_notify_send = subprocess.check_output( - ["which", "notify-send"] - ) - return run_which_for_notify_send.decode("utf-8") - except subprocess.CalledProcessError: - logger.exception("Unable to find notify-send.") - return False - except Exception: - logger.exception("Unhandled exception for finding notify-send.") - return False + This uses libnotify's tool of notfiy-send. + """ + pass def send_notification( self, @@ -87,14 +49,13 @@ def send_notification( **kwargs, ): try: - notification_title = " " if notification_title == "" else notification_title notification_subtitle = ( " " if notification_subtitle == "" else notification_subtitle ) generated_command = [ - self._notify_send_binary.strip(), + NOTIFY, notification_title, notification_subtitle, ] @@ -107,14 +68,17 @@ def send_notification( f"--app-name={shlex.quote(kwargs.get('application_name'))}" ) + if kwargs.get('notification_urgency'): + generated_command.extend(["-u", kwargs.get('notification_urgency')]) + logger.debug(f"Generated command: {generated_command}") if notification_audio: - if self._aplay_binary == False: + if APLAY == None: raise BinaryNotFound("aplay (Alsa)") subprocess.Popen( - [self._aplay_binary.strip(), notification_audio], + [APLAY, notification_audio], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, ) @@ -143,31 +107,6 @@ def __init__(self, **kwargs): interface="org.freedesktop.Notifications", ) - call_find_aplay = self._find_installed_aplay() - if not call_find_aplay: - # no Aplay is available. - self._aplay_binary = False - logger.debug("aplay binary not installed.. audio will not work!") - else: - self._aplay_binary = call_find_aplay - - if kwargs.get("linux_fallback_libnotify"): - self._fallback_to_libnotify = True - else: - self._fallback_to_libnotify = False - - @staticmethod - def _find_installed_aplay(): - """Function to find the path for notify-send""" - try: - run_which_for_aplay = subprocess.check_output(["which", "aplay"]) - return run_which_for_aplay.decode("utf-8") - except subprocess.CalledProcessError: - logger.exception("Unable to find aplay.") - return False - except Exception: - logger.exception("Unhandled exception for finding aplay.") - return False def send_notification( self, @@ -182,35 +121,23 @@ def send_notification( logger.debug("linux: opened dbus connection") except Exception: logger.exception("issue with opening DBUS connection!") - if self._fallback_to_libnotify == True: - logger.debug("falling back to libnotify!") - return LinuxNotifierLibNotify().send_notification( - notification_title, - notification_subtitle, - notification_icon, - notification_audio, - **kwargs, - ) - else: - logger.exception( - "there was an exception trying to open the dbus connection. fallback was not enabled, therefore this will return False." - ) - return False + return False try: notification_title = " " if notification_title == "" else notification_title notification_subtitle = ( " " if notification_subtitle == "" else notification_subtitle ) + if notification_audio: # TODO: https://specifications.freedesktop.org/notification-spec/latest/ar01s09.html # use sound param instead of relying on alsa? - if self._aplay_binary == False: + if APLAY == None: raise BinaryNotFound("aplay (Alsa)") subprocess.Popen( - [self._aplay_binary.strip(), notification_audio], + [APLAY, notification_audio], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, ) @@ -238,13 +165,4 @@ def send_notification( except Exception: logger.exception("issue with sending through dbus!") - if self._fallback_to_libnotify == True: - logger.debug("falling back to libnotify!") - return LinuxNotifierLibNotify().send_notification( - notification_title, - notification_subtitle, - notification_icon, - notification_audio, - **kwargs, - ) return False From 09954b9c32ddca8c081b99194a2047732a739988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 11:17:21 +0200 Subject: [PATCH 2/7] Fixed: issue with kwargs --- notifypy/os_notifiers/windows.py | 1 + 1 file changed, 1 insertion(+) diff --git a/notifypy/os_notifiers/windows.py b/notifypy/os_notifiers/windows.py index 72aa368..d9c6273 100644 --- a/notifypy/os_notifiers/windows.py +++ b/notifypy/os_notifiers/windows.py @@ -92,6 +92,7 @@ def send_notification( notification_icon, application_name, notification_audio, + **kwargs, ): generated_file = self._generate_notification_xml( notification_title=notification_title, From 88343a0e7ab83f7e0e8aff9899c73cea4bb04752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 11:23:29 +0200 Subject: [PATCH 3/7] Fixed: typo in function urgency --- notifypy/notify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifypy/notify.py b/notifypy/notify.py index c82a2eb..1b1c826 100644 --- a/notifypy/notify.py +++ b/notifypy/notify.py @@ -256,7 +256,7 @@ def application_name(self, new_application_name): @property def urgency(self): """The urgency of the notification (low, normal, critical) - Work only with libnotify (Linux), as of now + Works only with libnotify (Linux), as of now Returns: str: The urgency of the notification. From cbd3162cda647427246aaa3e4f3d969d311c7f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 15:08:02 +0200 Subject: [PATCH 4/7] 0.3.38 --- notifypy/__init__.py | 2 +- pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/notifypy/__init__.py b/notifypy/__init__.py index 4825930..b66e404 100644 --- a/notifypy/__init__.py +++ b/notifypy/__init__.py @@ -1,4 +1,4 @@ from .notify import Notify from .os_notifiers._base import BaseNotifier -__version__ = "0.3.31" +__version__ = "0.3.38" diff --git a/pyproject.toml b/pyproject.toml index 068e185..232dbb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "notify_py" -version = "0.3.31" +version = "0.3.38" description = "Cross-platform desktop notification library for Python" authors = ["Mustafa Mohamed "] repository = "https://github.com/ms7m/notify-py" diff --git a/setup.py b/setup.py index d788966..0be310a 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="notify_py", - version="0.3.31", + version="0.3.38", author="Mustafa Mohamed", author_email="ms7mohamed@gmail.com", description="Cross-platform desktop notification library for Python", From a96b1859faf35944a9be3774fc99fd7be7069095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 15:19:40 +0200 Subject: [PATCH 5/7] BSD support *** --- notifypy/notify.py | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/notifypy/notify.py b/notifypy/notify.py index 1b1c826..09c798a 100644 --- a/notifypy/notify.py +++ b/notifypy/notify.py @@ -105,26 +105,7 @@ def _selected_notification_system( else: selected_platform = platform.system() - if selected_platform == "Linux": - - if linux_use_legacy_notifier: - from .os_notifiers.linux import LinuxNotifierLibNotify - - return LinuxNotifierLibNotify - else: - - from .os_notifiers.linux import NOTIFY - - if NOTIFY: - from .os_notifiers.linux import LinuxNotifierLibNotify - - return LinuxNotifierLibNotify - else: - from .os_notifiers.linux import LinuxNotifier - - return LinuxNotifier - - elif selected_platform == "Darwin": + if selected_platform == "Darwin": from .os_notifiers.macos import MacOSNotifier return MacOSNotifier @@ -143,9 +124,25 @@ def _selected_notification_system( f"This version of Windows ({platform.release()}) is not supported." ) else: - raise UnsupportedPlatform( - "Platform couldn't be detected, please manually specifiy platform." - ) + if selected_platform != "Linux": + logger.warning(f'{selected_platform} might not be supported!') + + if linux_use_legacy_notifier: + from .os_notifiers.linux import LinuxNotifierLibNotify + + return LinuxNotifierLibNotify + else: + + from .os_notifiers.linux import NOTIFY + + if NOTIFY: + from .os_notifiers.linux import LinuxNotifierLibNotify + + return LinuxNotifierLibNotify + else: + from .os_notifiers.linux import LinuxNotifier + + return LinuxNotifier @staticmethod def _verify_audio_path(new_audio_path): From d19e99bb3a476a419ea931d12a23062c56888681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Wed, 23 Nov 2022 16:06:20 +0200 Subject: [PATCH 6/7] Added: Contributor GiorgosXou --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6d1fbea..4aa3a62 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,7 @@ You may need to add ``python3 -m`` to the beginning. - [Leterax](https://github.com/Leterax) - [jnoortheen](https://github.com/jnoortheen) - [dynobo](https://github.com/dynobo) +- [Xou](https://github.com/GiorgosXou) --- From 5b3225dd5ef4766368e80b9efb965f8f836af2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=AE?= Date: Sun, 27 Nov 2022 10:41:05 +0200 Subject: [PATCH 7/7] fix: inherit correct Exception class | @mingmingrr | #39 --- notifypy/exceptions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifypy/exceptions.py b/notifypy/exceptions.py index e608f98..421202e 100644 --- a/notifypy/exceptions.py +++ b/notifypy/exceptions.py @@ -1,7 +1,7 @@ # Custom and Clear Exceptions for NotifyPy -class BaseNotifyPyException(BaseException): +class BaseNotifyPyException(Exception): """Base Exception to be Inheritied"""