# Herald of Completion
[![Version](https://img.shields.io/github/v/release/sho-87/herald-of-completion?include_prereleases&sort=semver)](https://pypi.org/project/herald-of-completion/)
[![pypi](https://img.shields.io/pypi/pyversions/herald-of-completion)](https://pypi.org/project/herald-of-completion/)
![CI](https://img.shields.io/github/actions/workflow/status/sho-87/herald-of-completion/lint_test.yml?branch=develop)
[![Issues](https://img.shields.io/github/issues/sho-87/herald-of-completion)](https://github.com/sho-87/herald-of-completion/issues)
[![Donate](https://img.shields.io/badge/Buy%20me%20a%20coffee-donate-blue "Donate")](https://www.buymeacoffee.com/simonho)
<p align="center">
<img src="https://raw.githubusercontent.com/sho-87/herald-of-completion/master/docs/source/_static/herald.png" >
</p>
Hark! The herald of completion has arrived ... to let you know when your long-running tasks are done.
Decorate your functions with messengers, who will send a notification to you when your function has finished running.
The notification can contain a message and, optionally, the traceback if your function failed.
## Installation
```bash
pip install herald-of-completion
```
## Usage
Wrap the `@herald` decorator around the function you want to be notified about:
```python
from herald.decorators import Herald
from herald.messengers import DiscordMessenger
herald = Herald(".env") # Specify location of your .env settings file
# herald is the name of your decorator
discord = DiscordMessenger() # create a new messenger
@herald(discord) # wrap decorator around the function, with the messenger you want to use
def my_function():
a = [1, 2, 3]
return a
```
You can send multiple messengers at the same time:
```python
from herald.decorators import Herald
from herald.messengers import DiscordMessenger, EmailMessenger
herald = Herald(".env")
discord = DiscordMessenger()
email = EmailMessenger("recipient@email.com") # some messengers take arguments
@herald([discord, email]) # multiple messengers can be used at the same time
def my_function():
a = [1, 2, 3]
return a
```
### Options
By default, Herald will send a basic notification message indicating whether the function finished successfully or with an error. You can pass in a custom message to use instead:
```python
@herald(email, message="My custom message")
```
Passing `send_result=True` to the decorator will send the return value of your function through the messenger. This also includes notifying you of any exceptions that were raised:
```python
@herald(email, send_result=True) # defaults to True
def my_function():
a = [1, 2, 3]
return a[100] # if an exception is raised, `send_result=True` will also send the traceback
```
Passing `send_args=True` will show the `args` and `kwargs` the function was called with:
```python
@herald(email, send_args=True) # defaults to True
def my_function(var1, var2):
return ", ".join([var1, var2])
my_function("Hello", var2="world") # function call will be notified with all args and kwargs
```
### Manual notifications
There may be times where you want to send a notification without using a decorator / tying it to a specific function.
A utility function, `send_notification()`, can be used for this purpose. To use this, you'll need to construct your own `TaskInfo` object (see: [fields](https://github.com/sho-87/herald-of-completion/blob/master/src/herald/types.py)) containing the notification contents:
```python
from herald.types import TaskInfo
from herald.utils import send_notification # import the utility
discord = DiscordMessenger()
email = EmailMessenger()
info = TaskInfo(message="custom message", ...) # create TaskInfo with contents of the message
send_notification([discord, email], info, ".env") # pass in path to your .env file, if required
```
For more details about usage, the full API documentation can be found here: [documentation](https://sho-87.github.io/herald-of-completion/)
### .env settings
Some messengers require credentials and/or additional settings to work. These values are stored in a `.env` file.
Pass the location of this file to the `Herald` constructor, which will pass the values down to your messengers.
The `.env` file should look something like [this](https://github.com/sho-87/herald-of-completion/blob/master/tests/test.env). You only need settings for the messengers you want to use:
```text
# Discord settings
WEBHOOK_URL="https://discord.com/..."
# Email settings
SMTP_SERVER="smtp.gmail.com"
SMTP_PORT=587
SMTP_STARTTLS=True
SMTP_USER="user@gmail.com"
SMTP_PASSWORD="password"
```
Given the contents of this file, make sure you don't check it in to version control!
#### Explanation
| Name | Value Type | Messenger | Description |
| --------------- | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `WEBHOOK_URL` | str | Discord | The webhook URL for your server. Instructions [here](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |
| `SMTP_SERVER` | str | Email | STMP server of the email address you want to send _from_ |
| `SMTP_PORT` | int | Email | STMP port of the email address you want to send _from_ |
| `SMTP_STARTTLS` | bool | Email | Whether your server uses STARTTLS for authentication |
| `SMTP_USER` | str | Email | Your email username |
| `SMTP_PASSWORD` | str | Email | Your email password |
## Contribution
### Creating a new messenger
Creating a new messenger is straightforward and requires only 1 file:
1. Create a new module in `src/herald/messengers/`
2. Your class name should take the form `<Name>Messenger` and inherit the base `Messenger` abstract class. Example: `class DiscordMessenger(Messenger): ...`
3. Your class must implement the abstract methods defined in the base `Messenger` class [here](https://github.com/sho-87/herald-of-completion/blob/develop/src/herald/types.py)
4. Those methods define how your messenger sets it's secret values, and how it uses those settings to send a notification
5. Finally, import your messenger in the `__init__.py` file [here](https://github.com/sho-87/herald-of-completion/blob/develop/src/herald/messengers/__init__.py). This shortens the import path for users.
The `notify()` method of your messenger will receive a [TaskInfo](https://github.com/sho-87/herald-of-completion/blob/master/src/herald/types.py) dataclass object. You can use the dataclass' fields (e.g. `name`, `header`) to construct custom notification messages.
**Note**: Pull requests should be made to the `develop` branch.
### Tests
Unit and integration tests are located [here](https://github.com/sho-87/herald-of-completion/tree/develop/tests).
Tests should be run using `pytest`.
### Code style
The project is formatted using the `black` formatter.
Docstrings should follow the [Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) (with a few tweaks to help with Sphinx generation of documentation pages). Use the docstrings throughout the codebase as a guide.
Raw data
{
"_id": null,
"home_page": "https://github.com/sho-87/herald-of-completion",
"name": "herald-of-completion",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "notification,task,completion,function,long-running",
"author": "Simon Ho",
"author_email": "simonho.ubc@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/37/ea/3b25ad179c80afb6f692c5164570d08fe4b7b7325e1b66cb529060a95d89/herald-of-completion-0.3.0.tar.gz",
"platform": null,
"description": "# Herald of Completion\n\n[![Version](https://img.shields.io/github/v/release/sho-87/herald-of-completion?include_prereleases&sort=semver)](https://pypi.org/project/herald-of-completion/)\n[![pypi](https://img.shields.io/pypi/pyversions/herald-of-completion)](https://pypi.org/project/herald-of-completion/)\n![CI](https://img.shields.io/github/actions/workflow/status/sho-87/herald-of-completion/lint_test.yml?branch=develop)\n[![Issues](https://img.shields.io/github/issues/sho-87/herald-of-completion)](https://github.com/sho-87/herald-of-completion/issues)\n[![Donate](https://img.shields.io/badge/Buy%20me%20a%20coffee-donate-blue \"Donate\")](https://www.buymeacoffee.com/simonho)\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/sho-87/herald-of-completion/master/docs/source/_static/herald.png\" >\n</p>\n\nHark! The herald of completion has arrived ... to let you know when your long-running tasks are done.\n\nDecorate your functions with messengers, who will send a notification to you when your function has finished running.\n\nThe notification can contain a message and, optionally, the traceback if your function failed.\n\n## Installation\n\n```bash\npip install herald-of-completion\n```\n\n## Usage\n\nWrap the `@herald` decorator around the function you want to be notified about:\n\n```python\nfrom herald.decorators import Herald\nfrom herald.messengers import DiscordMessenger\n\nherald = Herald(\".env\") # Specify location of your .env settings file\n # herald is the name of your decorator\n\ndiscord = DiscordMessenger() # create a new messenger\n\n@herald(discord) # wrap decorator around the function, with the messenger you want to use\ndef my_function():\n a = [1, 2, 3]\n return a\n```\n\nYou can send multiple messengers at the same time:\n\n```python\nfrom herald.decorators import Herald\nfrom herald.messengers import DiscordMessenger, EmailMessenger\n\nherald = Herald(\".env\")\n\ndiscord = DiscordMessenger()\nemail = EmailMessenger(\"recipient@email.com\") # some messengers take arguments\n\n@herald([discord, email]) # multiple messengers can be used at the same time\ndef my_function():\n a = [1, 2, 3]\n return a\n```\n\n### Options\n\nBy default, Herald will send a basic notification message indicating whether the function finished successfully or with an error. You can pass in a custom message to use instead:\n\n```python\n@herald(email, message=\"My custom message\")\n```\n\nPassing `send_result=True` to the decorator will send the return value of your function through the messenger. This also includes notifying you of any exceptions that were raised:\n\n```python\n@herald(email, send_result=True) # defaults to True\ndef my_function():\n a = [1, 2, 3]\n return a[100] # if an exception is raised, `send_result=True` will also send the traceback\n```\n\nPassing `send_args=True` will show the `args` and `kwargs` the function was called with:\n\n```python\n@herald(email, send_args=True) # defaults to True\ndef my_function(var1, var2):\n return \", \".join([var1, var2])\n\nmy_function(\"Hello\", var2=\"world\") # function call will be notified with all args and kwargs\n```\n\n### Manual notifications\n\nThere may be times where you want to send a notification without using a decorator / tying it to a specific function.\n\nA utility function, `send_notification()`, can be used for this purpose. To use this, you'll need to construct your own `TaskInfo` object (see: [fields](https://github.com/sho-87/herald-of-completion/blob/master/src/herald/types.py)) containing the notification contents:\n\n```python\nfrom herald.types import TaskInfo\nfrom herald.utils import send_notification # import the utility\n\ndiscord = DiscordMessenger()\nemail = EmailMessenger()\ninfo = TaskInfo(message=\"custom message\", ...) # create TaskInfo with contents of the message\n\nsend_notification([discord, email], info, \".env\") # pass in path to your .env file, if required\n```\n\nFor more details about usage, the full API documentation can be found here: [documentation](https://sho-87.github.io/herald-of-completion/)\n\n### .env settings\n\nSome messengers require credentials and/or additional settings to work. These values are stored in a `.env` file.\n\nPass the location of this file to the `Herald` constructor, which will pass the values down to your messengers.\n\nThe `.env` file should look something like [this](https://github.com/sho-87/herald-of-completion/blob/master/tests/test.env). You only need settings for the messengers you want to use:\n\n```text\n# Discord settings\nWEBHOOK_URL=\"https://discord.com/...\"\n\n# Email settings\nSMTP_SERVER=\"smtp.gmail.com\"\nSMTP_PORT=587\nSMTP_STARTTLS=True\nSMTP_USER=\"user@gmail.com\"\nSMTP_PASSWORD=\"password\"\n```\n\nGiven the contents of this file, make sure you don't check it in to version control!\n\n#### Explanation\n\n| Name | Value Type | Messenger | Description |\n| --------------- | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| `WEBHOOK_URL` | str | Discord | The webhook URL for your server. Instructions [here](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks) |\n| `SMTP_SERVER` | str | Email | STMP server of the email address you want to send _from_ |\n| `SMTP_PORT` | int | Email | STMP port of the email address you want to send _from_ |\n| `SMTP_STARTTLS` | bool | Email | Whether your server uses STARTTLS for authentication |\n| `SMTP_USER` | str | Email | Your email username |\n| `SMTP_PASSWORD` | str | Email | Your email password |\n\n## Contribution\n\n### Creating a new messenger\n\nCreating a new messenger is straightforward and requires only 1 file:\n\n1. Create a new module in `src/herald/messengers/`\n2. Your class name should take the form `<Name>Messenger` and inherit the base `Messenger` abstract class. Example: `class DiscordMessenger(Messenger): ...`\n3. Your class must implement the abstract methods defined in the base `Messenger` class [here](https://github.com/sho-87/herald-of-completion/blob/develop/src/herald/types.py)\n4. Those methods define how your messenger sets it's secret values, and how it uses those settings to send a notification\n5. Finally, import your messenger in the `__init__.py` file [here](https://github.com/sho-87/herald-of-completion/blob/develop/src/herald/messengers/__init__.py). This shortens the import path for users.\n\nThe `notify()` method of your messenger will receive a [TaskInfo](https://github.com/sho-87/herald-of-completion/blob/master/src/herald/types.py) dataclass object. You can use the dataclass' fields (e.g. `name`, `header`) to construct custom notification messages.\n\n**Note**: Pull requests should be made to the `develop` branch.\n\n### Tests\n\nUnit and integration tests are located [here](https://github.com/sho-87/herald-of-completion/tree/develop/tests).\n\nTests should be run using `pytest`.\n\n### Code style\n\nThe project is formatted using the `black` formatter.\n\nDocstrings should follow the [Google style](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) (with a few tweaks to help with Sphinx generation of documentation pages). Use the docstrings throughout the codebase as a guide.\n",
"bugtrack_url": null,
"license": "",
"summary": "Hark! The herald of completion has arrived ... to let you know when your long-running tasks are done.",
"version": "0.3.0",
"project_urls": {
"Homepage": "https://github.com/sho-87/herald-of-completion"
},
"split_keywords": [
"notification",
"task",
"completion",
"function",
"long-running"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "60352dfc45764128b2857c4753ac8045d6ba695cd609705e6b3388dd63127ba8",
"md5": "94e54a225d23b7e64354da59a13f24f1",
"sha256": "79fdf12d39310712c07b9adbeaaf74c4995d8170c67fc2942095f6e4e4c420dd"
},
"downloads": -1,
"filename": "herald_of_completion-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "94e54a225d23b7e64354da59a13f24f1",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 24342,
"upload_time": "2023-04-30T22:50:41",
"upload_time_iso_8601": "2023-04-30T22:50:41.515534Z",
"url": "https://files.pythonhosted.org/packages/60/35/2dfc45764128b2857c4753ac8045d6ba695cd609705e6b3388dd63127ba8/herald_of_completion-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "37ea3b25ad179c80afb6f692c5164570d08fe4b7b7325e1b66cb529060a95d89",
"md5": "d98da8dcb7da3ff48691404460e181eb",
"sha256": "695bd8b3b95bf43326c27421034d803e5ccfc020b216f4e239cb6baac1e9cbae"
},
"downloads": -1,
"filename": "herald-of-completion-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "d98da8dcb7da3ff48691404460e181eb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 25228,
"upload_time": "2023-04-30T22:50:43",
"upload_time_iso_8601": "2023-04-30T22:50:43.444647Z",
"url": "https://files.pythonhosted.org/packages/37/ea/3b25ad179c80afb6f692c5164570d08fe4b7b7325e1b66cb529060a95d89/herald-of-completion-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-30 22:50:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "sho-87",
"github_project": "herald-of-completion",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "herald-of-completion"
}