django-unified-signals


Namedjango-unified-signals JSON
Version 0.1.1 PyPI version JSON
download
home_pagehttps://github.com/ivellios/django-unified-signals
SummaryDjango Signals extension for unifying data passed to receivers.
upload_time2023-09-20 13:22:36
maintainer
docs_urlNone
authorJanusz Kamieński
requires_python>=3.9,<4.0
licenseMIT
keywords django signals
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Django Unified Signals

[![Continuous Integration](https://github.com/ivellios/django-unified-signals/actions/workflows/ci.yaml/badge.svg)](https://github.com/ivellios/django-unified-signals/actions/workflows/ci.yaml)

This package extends behavior of the Django Signals, by unifying the data passed
when the signal is sent. That way both: the sender and the receiver can be sure 
that the data passed is always of the same type.

Django Signals are not very strict on the data that can be passed with [send method](https://docs.djangoproject.com/en/4.2/topics/signals/#django.dispatch.Signal.send).
Basically anything can be passed as the arguments and receivers 
need to be aware of that from the project documentation. It gets even worse when on one
side the signal send params change and the receivers' maintainers may not be aware of that. 
It gets even worse, when using send_robust method, which ignores all exceptions 
and any errors may pass without being noticed.

Using this package you have to define the message type class which object  
is always expected to be passed when sending the signal. That way receiver 
knows what type of message will be received. This package automates the process
of checking if the send message is following the contract.

## Installation

The package is [available on PyPI](https://pypi.org/project/django-unified-signals/): 

```bash
pip install django-unified-signals
```

## Usage

Let's start by defining the message structure. It can be any class you want.
In the example we will use `dataclass`:

```python
import dataclasses

@dataclasses.dataclass
class UserMessage:
    name: str
    age: int
```

Now that we have the message structure defined, we can create the signal:

```python

from unified_signals import UnifiedSignal

user_deactivated_signal = UnifiedSignal(UserMessage)
```

It extends the standard `django.dispatch.Signal` class, 
so it can be used in the same way.

```python
user_deactivated_signal.send(sender, UserMessage(name='John', age=30))
```

The receiver can be defined in the same way as for the standard Django Signal:

```python
@receiver(user_deactivated_signal)
def handle_user_deactivated(sender, message: UserMessage, **kwargs):
    print(message.name)
    print(message.age)
    ...
```

The difference is that the message is always of the same type, so the receiver
can be sure that the message is always of the same type. If the message is not
of the expected type when sending the signal, the `unified_signals.exceptions.UnifiedSignalMessageTypeError` 
exception will be raised.

```python
user_deactivated_signal.send(sender, 'not a message') # raises UnifiedSignalMessageTypeError
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/ivellios/django-unified-signals",
    "name": "django-unified-signals",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<4.0",
    "maintainer_email": "",
    "keywords": "django,signals",
    "author": "Janusz Kamie\u0144ski",
    "author_email": "200957+ivellios@users.noreply.github.com",
    "download_url": "https://files.pythonhosted.org/packages/fa/b5/167284055a3ded96e04e2895acb8ab2434a35a7a0e1dc002e5c167210105/django_unified_signals-0.1.1.tar.gz",
    "platform": null,
    "description": "# Django Unified Signals\n\n[![Continuous Integration](https://github.com/ivellios/django-unified-signals/actions/workflows/ci.yaml/badge.svg)](https://github.com/ivellios/django-unified-signals/actions/workflows/ci.yaml)\n\nThis package extends behavior of the Django Signals, by unifying the data passed\nwhen the signal is sent. That way both: the sender and the receiver can be sure \nthat the data passed is always of the same type.\n\nDjango Signals are not very strict on the data that can be passed with [send method](https://docs.djangoproject.com/en/4.2/topics/signals/#django.dispatch.Signal.send).\nBasically anything can be passed as the arguments and receivers \nneed to be aware of that from the project documentation. It gets even worse when on one\nside the signal send params change and the receivers' maintainers may not be aware of that. \nIt gets even worse, when using send_robust method, which ignores all exceptions \nand any errors may pass without being noticed.\n\nUsing this package you have to define the message type class which object  \nis always expected to be passed when sending the signal. That way receiver \nknows what type of message will be received. This package automates the process\nof checking if the send message is following the contract.\n\n## Installation\n\nThe package is [available on PyPI](https://pypi.org/project/django-unified-signals/): \n\n```bash\npip install django-unified-signals\n```\n\n## Usage\n\nLet's start by defining the message structure. It can be any class you want.\nIn the example we will use `dataclass`:\n\n```python\nimport dataclasses\n\n@dataclasses.dataclass\nclass UserMessage:\n    name: str\n    age: int\n```\n\nNow that we have the message structure defined, we can create the signal:\n\n```python\n\nfrom unified_signals import UnifiedSignal\n\nuser_deactivated_signal = UnifiedSignal(UserMessage)\n```\n\nIt extends the standard `django.dispatch.Signal` class, \nso it can be used in the same way.\n\n```python\nuser_deactivated_signal.send(sender, UserMessage(name='John', age=30))\n```\n\nThe receiver can be defined in the same way as for the standard Django Signal:\n\n```python\n@receiver(user_deactivated_signal)\ndef handle_user_deactivated(sender, message: UserMessage, **kwargs):\n    print(message.name)\n    print(message.age)\n    ...\n```\n\nThe difference is that the message is always of the same type, so the receiver\ncan be sure that the message is always of the same type. If the message is not\nof the expected type when sending the signal, the `unified_signals.exceptions.UnifiedSignalMessageTypeError` \nexception will be raised.\n\n```python\nuser_deactivated_signal.send(sender, 'not a message') # raises UnifiedSignalMessageTypeError\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Django Signals extension for unifying data passed to receivers.",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://github.com/ivellios/django-unified-signals",
        "Repository": "https://github.com/ivellios/django-unified-signals"
    },
    "split_keywords": [
        "django",
        "signals"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "79cf5c316cd90a0e95599488b6911502223c06b7998a94d9d7569dd13c01885a",
                "md5": "b4dee6d5d6801049d6c3806a466fc491",
                "sha256": "7d54d7d0191998be0ac8252c0d75700511293022ea8ccdaa311ea06f116ea5d5"
            },
            "downloads": -1,
            "filename": "django_unified_signals-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b4dee6d5d6801049d6c3806a466fc491",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<4.0",
            "size": 4301,
            "upload_time": "2023-09-20T13:22:34",
            "upload_time_iso_8601": "2023-09-20T13:22:34.800664Z",
            "url": "https://files.pythonhosted.org/packages/79/cf/5c316cd90a0e95599488b6911502223c06b7998a94d9d7569dd13c01885a/django_unified_signals-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "fab5167284055a3ded96e04e2895acb8ab2434a35a7a0e1dc002e5c167210105",
                "md5": "27a82d328b8a24f254ade879191920d6",
                "sha256": "0971e163ed385fbc37941286d6ef8f314d38973876733300081628696b4b0ce6"
            },
            "downloads": -1,
            "filename": "django_unified_signals-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "27a82d328b8a24f254ade879191920d6",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<4.0",
            "size": 3633,
            "upload_time": "2023-09-20T13:22:36",
            "upload_time_iso_8601": "2023-09-20T13:22:36.240848Z",
            "url": "https://files.pythonhosted.org/packages/fa/b5/167284055a3ded96e04e2895acb8ab2434a35a7a0e1dc002e5c167210105/django_unified_signals-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-09-20 13:22:36",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ivellios",
    "github_project": "django-unified-signals",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "django-unified-signals"
}
        
Elapsed time: 0.15003s