The ``notifications.py`` module
===============================
.. py:module:: ansys.tools.common.notifications
Summary
-------
.. py:currentmodule:: notifications
.. tab-set::
.. tab-item:: Classes
.. list-table::
:header-rows: 0
:widths: auto
* - :py:obj:`~ansys.tools.common.notifications.AnsysNotifier`
- Desktop and multi-channel notifier for PyAnsys job-completion events.
.. tab-item:: Enums
.. list-table::
:header-rows: 0
:widths: auto
* - :py:obj:`~ansys.tools.common.notifications.NotificationChannel`
- Well-known apprise notification channel URL schemes.
* - :py:obj:`~ansys.tools.common.notifications.NotificationFormat`
- Body format of the notification.
* - :py:obj:`~ansys.tools.common.notifications.NotificationType`
- Notification type / type of the notification.
.. tab-item:: Functions
.. list-table::
:header-rows: 0
:widths: auto
* - :py:obj:`~get_notification_channels`
- Return the global default notification channels.
* - :py:obj:`~get_notification_level`
- Return the global default notification level.
* - :py:obj:`~get_notify_on_failure`
- Return the global default for whether failure notifications are sent.
* - :py:obj:`~get_failure_notification_level`
- Return the global default notification level used on failure.
* - :py:obj:`~set_notification_channels`
- Set the global default notification channels.
* - :py:obj:`~set_notification_level`
- Set the global default notification level.
* - :py:obj:`~set_notify_on_failure`
- Set whether a notification is sent globally when a decorated function fails.
* - :py:obj:`~set_failure_notification_level`
- Set the global default notification level used when a decorated function fails.
* - :py:obj:`~notify`
- Send a one-shot notification without creating a persistent notifier.
* - :py:obj:`~notify_on_completion`
- Send a notification when the decorated function finishes.
.. toctree::
:titlesonly:
:maxdepth: 1
:hidden:
AnsysNotifier
.. toctree::
:titlesonly:
:maxdepth: 1
:hidden:
NotificationChannel
NotificationFormat
NotificationType
Description
-----------
Desktop and multi-channel notification support for PyAnsys libraries.
This module exposes :class:`AnsysNotifier` for persistent use inside PyAnsys
library workflows and the convenience function :func:`notify` for one-shot
script usage.
Install the optional dependency before using this module::
pip install "ansys-tools-common[notifications]"
Quick start
-----------
>>> from ansys.tools.common.notifications import notify, NotificationType
>>> notify("Simulation complete.")
>>> notify("Solve diverged!", notification_type=NotificationType.FAILURE)
>>> from ansys.tools.common.notifications import NotificationChannel
>>> notify("Job done.", channels=[NotificationChannel.WINDOWS])
Module detail
-------------
.. py:function:: get_notification_channels() -> list[str] | None
Return the global default notification channels.
Returns
-------
list[str] | None
The channels set by :func:`set_notification_channels`, or ``None``
if no global default is set (desktop channel will be used).
.. py:function:: get_notification_level() -> NotificationType
Return the global default notification level.
Returns
-------
NotificationType
The level set by :func:`set_notification_level`.
.. py:function:: get_notify_on_failure() -> bool
Return the global default for whether failure notifications are sent.
Returns
-------
bool
The value set by :func:`set_notify_on_failure`.
.. py:function:: get_failure_notification_level() -> NotificationType
Return the global default notification level used on failure.
Returns
-------
NotificationType
The level set by :func:`set_failure_notification_level`.
.. py:function:: set_notification_channels(channels: list[NotificationChannel | str] | None) -> None
Set the global default notification channels.
Affects all subsequent calls to :func:`notify` and
:func:`notify_on_completion` that do not supply an explicit *channels*
argument. Setting *channels* to ``None`` reverts to the
automatically detected desktop channel.
Parameters
----------
channels : list[NotificationChannel | str] | None
A list of apprise-compatible channel URLs or :class:`NotificationChannel`
members, or ``None`` to reset to the OS desktop default.
Examples
--------
>>> set_notification_channels([NotificationChannel.SLACK + "token/channel"])
>>> set_notification_channels(["myfancychannel", "anotherchannel"])
>>> set_notification_channels(None) # reset to desktop default
.. py:function:: set_notification_level(level: NotificationType | str) -> None
Set the global default notification level.
Affects all subsequent calls to :func:`notify` and
:func:`notify_on_completion` that do not supply an explicit
*notification_type* argument.
Parameters
----------
level : NotificationType | str
A :class:`NotificationType` member or its string value
(``"info"``, ``"success"``, ``"warning"``, ``"failure"``).
Examples
--------
>>> set_notification_level("warning")
>>> set_notification_level(NotificationType.FAILURE)
.. py:function:: set_notify_on_failure(enabled: bool) -> None
Set whether a notification is sent globally when a decorated function fails.
Affects all subsequent calls to :func:`notify_on_completion` that do not
supply an explicit *notify_on_failure* argument.
Parameters
----------
enabled : bool
``True`` to send a failure notification (default), ``False`` to suppress it.
Examples
--------
>>> set_notify_on_failure(False)
.. py:function:: set_failure_notification_level(level: NotificationType | str) -> None
Set the global default notification level used when a decorated function fails.
Affects all subsequent calls to :func:`notify_on_completion` that do not
supply an explicit *failure_notification_type* argument.
Parameters
----------
level : NotificationType | str
A :class:`NotificationType` member or its string value
(``"info"``, ``"success"``, ``"warning"``, ``"failure"``).
Examples
--------
>>> set_failure_notification_level("warning")
>>> set_failure_notification_level(NotificationType.FAILURE)
.. py:function:: notify(message: str, title: str = 'PyAnsys', channels: list[NotificationChannel | str] | None = None, format: NotificationFormat = NotificationFormat.TEXT, notification_type: NotificationType | None = None) -> bool
Send a one-shot notification without creating a persistent notifier.
This convenience function is intended for simple script usage where a
persistent :class:`AnsysNotifier` instance is not needed.
Parameters
----------
message : str
Body of the notification.
title : str, optional
Notification title, by default ``"PyAnsys"``.
channels : list[NotificationChannel | str] | None, optional
Apprise channel URLs. When ``None``, the global default set by
:func:`set_notification_channel` is used; if that is also ``None``,
the native desktop notification service for the current OS is used.
format : NotificationFormat, optional
Body format, by default :attr:`NotificationFormat.TEXT`.
notification_type : NotificationType | None, optional
notification_type level. When ``None``, the global default set by
:func:`set_notification_level` is used (initially
:attr:`NotificationType.INFO`).
Returns
-------
bool
``True`` if delivered successfully to all channels.
Examples
--------
Minimal usage — sends a desktop notification:
>>> from ansys.tools.common.notifications import notify
>>> notify("Simulation complete.")
Failure notification:
>>> notify("Solve diverged!", notification_type=NotificationType.FAILURE)
Multi-channel:
>>> notify("Job done.", channels=[NotificationChannel.WINDOWS, NotificationChannel.SLACK + "token/channel"])
.. py:function:: notify_on_completion(message: str | None = None, *, title: str = 'PyAnsys', channels: list[NotificationChannel | str] | None = None, format: NotificationFormat = NotificationFormat.TEXT, notification_type: NotificationType | None = None, notify_on_failure: bool | None = None, failure_notification_type: NotificationType | None = None, failure_message: str | None = None) -> collections.abc.Callable
Send a notification when the decorated function finishes.
Wraps a callable so that a notification is dispatched automatically on
success (and optionally on failure) without any extra code at each call
site.
Parameters
----------
message : str | None, optional
Body of the notification. When ``None`` a default message is
built from the wrapped function's name: ``" completed."``.
title : str, optional
Notification title, by default ``"PyAnsys"``.
channels : list[NotificationChannel | str] | None, optional
Apprise channel URLs. When ``None``, the global default set by
:func:`set_notification_channel` is used; if that is also ``None``,
the native desktop notification service for the current OS is used.
format : NotificationFormat, optional
Body format, by default :attr:`NotificationFormat.TEXT`.
notification_type : NotificationType | None, optional
Notification type used for the notification. When ``None``, the
global default set by :func:`set_notification_level` is used
(initially :attr:`NotificationType.INFO`).
notify_on_failure : bool | None, optional
When ``True`` a notification is also sent if the wrapped function
raises an exception. The exception is always re-raised. When
``None``, the global default set by :func:`set_notify_on_failure`
is used (initially ``True``).
failure_notification_type : NotificationType | None, optional
Notification type used for the failure notification. When ``None``,
the global default set by :func:`set_failure_notification_level` is
used (initially :attr:`NotificationType.FAILURE`).
failure_message : str | None, optional
Body of the failure notification. When ``None`` a default message is
built from the wrapped function's name and the exception:
``" failed: "``.
Returns
-------
Callable
A decorator that wraps the target function.
Examples
--------
Send a desktop notification when the function returns:
>>> from ansys.tools.common.notifications import notify_on_completion
>>> @notify_on_completion("Simulation complete.")
... def run_simulation():
... pass
Auto-generate the message from the function name:
>>> @notify_on_completion()
... def solve():
... pass
Custom channels and failure notification:
>>> @notify_on_completion(
... channels=[NotificationChannel.SLACK + "token/channel"],
... notify_on_failure=True,
... )
... def long_running_job():
... pass