desktop-notifier


Namedesktop-notifier JSON
Version 5.0.1 PyPI version JSON
download
home_pageNone
SummaryPython library for cross-platform desktop notifications
upload_time2024-07-07 11:23:17
maintainerNone
docs_urlNone
authorNone
requires_python>=3.7
licenseMIT
keywords desktop-notifier notifications notification center push notifications toast notifications
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# Desktop Notifier

[![PyPi Release](https://img.shields.io/pypi/v/desktop-notifier.svg)](https://pypi.org/project/desktop-notifier/)
[![Pyversions](https://img.shields.io/pypi/pyversions/desktop-notifier.svg)](https://pypi.org/pypi/desktop-notifier/)
[![Documentation Status](https://readthedocs.org/projects/desktop-notifier/badge/?version=latest)](https://desktop-notifier.readthedocs.io/en/latest/?badge=latest)

`desktop-notifier`  is a Python library for cross-platform desktop notifications.
Currently supported platforms are:

* Linux via the dbus service org.freedesktop.Notifications
* macOS and iOS via the Notification Center framework
* Windows via the WinRT / Python bridge

## Features

Where supported by the native platform APIs, `desktop-notifier` allows for:

* Clickable notifications with callbacks on user interaction
* Multiple action buttons
* A single reply field (e.g., for chat notifications)
* Notification sounds
* Notification threads (grouping notifications by topic)
* Limiting the maximum number of notifications shown in the notification center

An example of how some of this looks like on macOS:

![gif](https://github.com/samschott/desktop-notifier/blob/main/screenshots/macOS.gif?raw=true)

An exhaustive list of features and their platform support is provided in the
[documentation](https://desktop-notifier.readthedocs.io/en/latest/background/platform_support.html).
In addition, you can query supported features at runtime with
`DesktopNotifier.get_capabilities()`.

Any options or configurations which are not supported by the platform will be silently
ignored.

## Installation

From PyPI:

```
pip3 install -U desktop-notifier
```

## Usage

The main API consists of asynchronous methods which need to be awaited. Basic usage only
requires the user to specify a notification title and message. For example:

```Python
import asyncio
from desktop_notifier import DesktopNotifier

notifier = DesktopNotifier()

async def main():
    await notifier.send(title="Hello world!", message="Sent from Python")

asyncio.run(main())
```

By default, "Python" will be used as the app name for all notifications, but you can
manually specify an app name and icon in the ``DesktopNotifier`` constructor. Advanced
usage also allows setting different notification options such as urgency, buttons,
callbacks, etc. For example, for the gif displayed above:

```Python
import asyncio
import signal

from desktop_notifier import DesktopNotifier, Urgency, Button, ReplyField, DEFAULT_SOUND


async def main() -> None:
    notifier = DesktopNotifier(
        app_name="Sample App",
        notification_limit=10,
    )

    await notifier.send(
        title="Julius Caesar",
        message="Et tu, Brute?",
        urgency=Urgency.Critical,
        buttons=[
            Button(
                title="Mark as read",
                on_pressed=lambda: print("Marked as read"),
            )
        ],
        reply_field=ReplyField(
            on_replied=lambda text: print("Brutus replied:", text),
        ),
        on_clicked=lambda: print("Notification clicked"),
        on_dismissed=lambda: print("Notification dismissed"),
        sound=DEFAULT_SOUND,
    )

    # Run the event loop forever to respond to user interactions with the notification.
    stop_event = asyncio.Event()
    loop = asyncio.get_running_loop()

    loop.add_signal_handler(signal.SIGINT, stop_event.set)
    loop.add_signal_handler(signal.SIGTERM, stop_event.set)

    await stop_event.wait()

asyncio.run(main())
```

## Event loop integration

Using the asynchronous API is highly recommended to prevent multiple milliseconds of
blocking IO from DBus or Cocoa APIs. In addition, execution of callbacks requires a
running event loop. On Linux, an asyncio event loop will be sufficient but macOS
requires a running [CFRunLoop](https://developer.apple.com/documentation/corefoundation/cfrunloop-rht).

You can use [rubicon-objc](https://github.com/beeware/rubicon-objc) to integrate a Core
Foundation CFRunLoop with asyncio:

```Python
import asyncio
from rubicon.objc.eventloop import EventLoopPolicy

# Install the event loop policy
asyncio.set_event_loop_policy(EventLoopPolicy())
```

Desktop-notifier itself uses Rubicon Objective-C to interface with Cocoa APIs. A full
example integrating with the CFRunLoop is given in
[examples/eventloop.py](examples/eventloop.py). Please refer to the
[Rubicon Objective-C docs](https://rubicon-objc.readthedocs.io/en/latest/how-to/async.html)
for more information.

Likewise, you can integrate the asyncio event loop with a Gtk main loop on Gnome using
[gbulb](https://pypi.org/project/gbulb). This is not required for full functionality
but may be convenient when developing a Gtk app.

## Notes on macOS

On macOS 10.14 and higher, the implementation uses the `UNUserNotificationCenter`
instead of the deprecated `NSUserNotificationCenter`. `UNUserNotificationCenter`
only allows signed executables to send desktop notifications. This means that
notifications will only work if the Python executable or bundled app has been signed.
Note that the installer from [python.org](https://python.org) provides a properly signed
Python framework but **homebrew does not** (manually signing the executable installed
by homebrew *should* work as well).

If you freeze your code with PyInstaller or a similar packaging solution, you must sign
the resulting app bundle for notifications to work. An ad-hoc signature will be
sufficient but signing with an Apple developer certificate is recommended for
distribution and may be required on future releases of macOS.

## Design choices

This package is opinionated in a few ways:

* It does not try to work around platform restrictions, such as changing the app icon on
  macOS. Workarounds would be hacky and likely be rejected by an App Store review.
* The main API consists of async methods and a running event loop is required to respond
  to user interactions with a notification. This simplifies integration with GUI apps.
* Dependencies are pure Python packages without extension modules. This simplifies app
  bundling and distribution. We make an exception for Windows because interoperability
  with the Windows Runtime is difficult to achieve without extension modules.
* If a certain feature is not supported by a platform, using it will not raise an
  exception. This allows clients to use a wide feature set where available without
  worrying about exception handling.
* If a notification cannot be scheduled, this is logged as a warning and does not raise
  an exception. Most platforms allow the user to control if and how notifications are
  delivered and notification delivery therefore cannot be taken as guaranteed.

## Dependencies

* [dbus-next](https://github.com/altdesktop/python-dbus-next) on Linux
* [rubicon-objc](https://github.com/beeware/rubicon-objc) on macOS
* [pywinrt](https://github.com/pywinrt/pywinrt) on Windows

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "desktop-notifier",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "desktop-notifier, notifications, Notification Center, push notifications, Toast notifications",
    "author": null,
    "author_email": "Sam Schott <sam.schott@outlook.com>",
    "download_url": "https://files.pythonhosted.org/packages/47/a9/6b46dbdc8d81fd2d645d69767b91447717a247787abd2f2ed8f955cf77f5/desktop_notifier-5.0.1.tar.gz",
    "platform": null,
    "description": "\n# Desktop Notifier\n\n[![PyPi Release](https://img.shields.io/pypi/v/desktop-notifier.svg)](https://pypi.org/project/desktop-notifier/)\n[![Pyversions](https://img.shields.io/pypi/pyversions/desktop-notifier.svg)](https://pypi.org/pypi/desktop-notifier/)\n[![Documentation Status](https://readthedocs.org/projects/desktop-notifier/badge/?version=latest)](https://desktop-notifier.readthedocs.io/en/latest/?badge=latest)\n\n`desktop-notifier`  is a Python library for cross-platform desktop notifications.\nCurrently supported platforms are:\n\n* Linux via the dbus service org.freedesktop.Notifications\n* macOS and iOS via the Notification Center framework\n* Windows via the WinRT / Python bridge\n\n## Features\n\nWhere supported by the native platform APIs, `desktop-notifier` allows for:\n\n* Clickable notifications with callbacks on user interaction\n* Multiple action buttons\n* A single reply field (e.g., for chat notifications)\n* Notification sounds\n* Notification threads (grouping notifications by topic)\n* Limiting the maximum number of notifications shown in the notification center\n\nAn example of how some of this looks like on macOS:\n\n![gif](https://github.com/samschott/desktop-notifier/blob/main/screenshots/macOS.gif?raw=true)\n\nAn exhaustive list of features and their platform support is provided in the\n[documentation](https://desktop-notifier.readthedocs.io/en/latest/background/platform_support.html).\nIn addition, you can query supported features at runtime with\n`DesktopNotifier.get_capabilities()`.\n\nAny options or configurations which are not supported by the platform will be silently\nignored.\n\n## Installation\n\nFrom PyPI:\n\n```\npip3 install -U desktop-notifier\n```\n\n## Usage\n\nThe main API consists of asynchronous methods which need to be awaited. Basic usage only\nrequires the user to specify a notification title and message. For example:\n\n```Python\nimport asyncio\nfrom desktop_notifier import DesktopNotifier\n\nnotifier = DesktopNotifier()\n\nasync def main():\n    await notifier.send(title=\"Hello world!\", message=\"Sent from Python\")\n\nasyncio.run(main())\n```\n\nBy default, \"Python\" will be used as the app name for all notifications, but you can\nmanually specify an app name and icon in the ``DesktopNotifier`` constructor. Advanced\nusage also allows setting different notification options such as urgency, buttons,\ncallbacks, etc. For example, for the gif displayed above:\n\n```Python\nimport asyncio\nimport signal\n\nfrom desktop_notifier import DesktopNotifier, Urgency, Button, ReplyField, DEFAULT_SOUND\n\n\nasync def main() -> None:\n    notifier = DesktopNotifier(\n        app_name=\"Sample App\",\n        notification_limit=10,\n    )\n\n    await notifier.send(\n        title=\"Julius Caesar\",\n        message=\"Et tu, Brute?\",\n        urgency=Urgency.Critical,\n        buttons=[\n            Button(\n                title=\"Mark as read\",\n                on_pressed=lambda: print(\"Marked as read\"),\n            )\n        ],\n        reply_field=ReplyField(\n            on_replied=lambda text: print(\"Brutus replied:\", text),\n        ),\n        on_clicked=lambda: print(\"Notification clicked\"),\n        on_dismissed=lambda: print(\"Notification dismissed\"),\n        sound=DEFAULT_SOUND,\n    )\n\n    # Run the event loop forever to respond to user interactions with the notification.\n    stop_event = asyncio.Event()\n    loop = asyncio.get_running_loop()\n\n    loop.add_signal_handler(signal.SIGINT, stop_event.set)\n    loop.add_signal_handler(signal.SIGTERM, stop_event.set)\n\n    await stop_event.wait()\n\nasyncio.run(main())\n```\n\n## Event loop integration\n\nUsing the asynchronous API is highly recommended to prevent multiple milliseconds of\nblocking IO from DBus or Cocoa APIs. In addition, execution of callbacks requires a\nrunning event loop. On Linux, an asyncio event loop will be sufficient but macOS\nrequires a running [CFRunLoop](https://developer.apple.com/documentation/corefoundation/cfrunloop-rht).\n\nYou can use [rubicon-objc](https://github.com/beeware/rubicon-objc) to integrate a Core\nFoundation CFRunLoop with asyncio:\n\n```Python\nimport asyncio\nfrom rubicon.objc.eventloop import EventLoopPolicy\n\n# Install the event loop policy\nasyncio.set_event_loop_policy(EventLoopPolicy())\n```\n\nDesktop-notifier itself uses Rubicon Objective-C to interface with Cocoa APIs. A full\nexample integrating with the CFRunLoop is given in\n[examples/eventloop.py](examples/eventloop.py). Please refer to the\n[Rubicon Objective-C docs](https://rubicon-objc.readthedocs.io/en/latest/how-to/async.html)\nfor more information.\n\nLikewise, you can integrate the asyncio event loop with a Gtk main loop on Gnome using\n[gbulb](https://pypi.org/project/gbulb). This is not required for full functionality\nbut may be convenient when developing a Gtk app.\n\n## Notes on macOS\n\nOn macOS 10.14 and higher, the implementation uses the `UNUserNotificationCenter`\ninstead of the deprecated `NSUserNotificationCenter`. `UNUserNotificationCenter`\nonly allows signed executables to send desktop notifications. This means that\nnotifications will only work if the Python executable or bundled app has been signed.\nNote that the installer from [python.org](https://python.org) provides a properly signed\nPython framework but **homebrew does not** (manually signing the executable installed\nby homebrew *should* work as well).\n\nIf you freeze your code with PyInstaller or a similar packaging solution, you must sign\nthe resulting app bundle for notifications to work. An ad-hoc signature will be\nsufficient but signing with an Apple developer certificate is recommended for\ndistribution and may be required on future releases of macOS.\n\n## Design choices\n\nThis package is opinionated in a few ways:\n\n* It does not try to work around platform restrictions, such as changing the app icon on\n  macOS. Workarounds would be hacky and likely be rejected by an App Store review.\n* The main API consists of async methods and a running event loop is required to respond\n  to user interactions with a notification. This simplifies integration with GUI apps.\n* Dependencies are pure Python packages without extension modules. This simplifies app\n  bundling and distribution. We make an exception for Windows because interoperability\n  with the Windows Runtime is difficult to achieve without extension modules.\n* If a certain feature is not supported by a platform, using it will not raise an\n  exception. This allows clients to use a wide feature set where available without\n  worrying about exception handling.\n* If a notification cannot be scheduled, this is logged as a warning and does not raise\n  an exception. Most platforms allow the user to control if and how notifications are\n  delivered and notification delivery therefore cannot be taken as guaranteed.\n\n## Dependencies\n\n* [dbus-next](https://github.com/altdesktop/python-dbus-next) on Linux\n* [rubicon-objc](https://github.com/beeware/rubicon-objc) on macOS\n* [pywinrt](https://github.com/pywinrt/pywinrt) on Windows\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python library for cross-platform desktop notifications",
    "version": "5.0.1",
    "project_urls": {
        "Homepage": "https://github.com/samschott/desktop-notifier"
    },
    "split_keywords": [
        "desktop-notifier",
        " notifications",
        " notification center",
        " push notifications",
        " toast notifications"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3287b8e4235df77cd20cea70e46ff82e99abc1573ddf8f1156f9fec5d86f37b8",
                "md5": "b99e83ca80caf955730d110573eac113",
                "sha256": "eacfd923fd6fd21daede6de6ba3dc86cbaa6511cf3a8b810a589263b692be967"
            },
            "downloads": -1,
            "filename": "desktop_notifier-5.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b99e83ca80caf955730d110573eac113",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 33276,
            "upload_time": "2024-07-07T11:23:15",
            "upload_time_iso_8601": "2024-07-07T11:23:15.012124Z",
            "url": "https://files.pythonhosted.org/packages/32/87/b8e4235df77cd20cea70e46ff82e99abc1573ddf8f1156f9fec5d86f37b8/desktop_notifier-5.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "47a96b46dbdc8d81fd2d645d69767b91447717a247787abd2f2ed8f955cf77f5",
                "md5": "4be1e6ce17ab6d3495553a1e15656c1d",
                "sha256": "8fbe550fd0e765ec79014a04a087824edd4a3f11577a0b0a892e1cb892f5d7ea"
            },
            "downloads": -1,
            "filename": "desktop_notifier-5.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "4be1e6ce17ab6d3495553a1e15656c1d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 32731,
            "upload_time": "2024-07-07T11:23:17",
            "upload_time_iso_8601": "2024-07-07T11:23:17.029644Z",
            "url": "https://files.pythonhosted.org/packages/47/a9/6b46dbdc8d81fd2d645d69767b91447717a247787abd2f2ed8f955cf77f5/desktop_notifier-5.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-07-07 11:23:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "samschott",
    "github_project": "desktop-notifier",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "desktop-notifier"
}
        
Elapsed time: 1.33981s