-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
3,784 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Authorized and unauthorized licenses in LOWER CASE | ||
[Licenses] | ||
authorized_licenses: | ||
BSD | ||
new BSD | ||
BSD license | ||
new BDS license | ||
simplified BSD | ||
Apache | ||
Apache 2.0 | ||
Apache Software | ||
Apache software license | ||
gnu LGPL | ||
LGPL with exceptions or zpl | ||
ISC license | ||
ISC license (ISCL) | ||
MIT | ||
MIT license | ||
Python Software Foundation | ||
python software foundation license | ||
zpl 2.1 | ||
|
||
unauthorized_licenses: | ||
GPL v3 | ||
GPL | ||
GNU General Public License v2 or later (GPLv2+) | ||
|
||
|
||
[Authorized Packages] | ||
# Python software license (see http://zesty.ca/python/uuid.README.txt) | ||
uuid: 1.25,>=1.30 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#!/usr/bin/env python | ||
"""Django's command-line utility for administrative tasks.""" | ||
import os | ||
import sys | ||
|
||
|
||
def main(): | ||
"""Run administrative tasks.""" | ||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tests.testapp.settings") | ||
|
||
from django.core.management import execute_from_command_line | ||
|
||
execute_from_command_line(sys.argv) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[mypy] | ||
warn_return_any = True | ||
warn_unused_configs = True | ||
|
||
[mypy-unified_signals.*] | ||
ignore_missing_imports = True | ||
|
||
[mypy-celery.*] | ||
ignore_missing_imports = True |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
[tool.poetry] | ||
name = "celery-signal-receivers" | ||
version = "0.1.0" | ||
description = "Extension for the Django signal receivers to process them asynchronously as the Celery tasks." | ||
authors = ["Janusz Kamieński <[email protected]>"] | ||
license = "MIT" | ||
readme = "README.md" | ||
homepage = "https://github.com/ivellios/celery-signal-receivers" | ||
repository = "https://github.com/ivellios/celery-signal-receivers" | ||
keywords = ["django", "signals", "celery"] | ||
classifiers = [ | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"License :: OSI Approved :: MIT License", | ||
"Operating System :: OS Independent", | ||
"Framework :: Django :: 4.0", | ||
"Framework :: Django :: 4.1", | ||
"Framework :: Django :: 4.2", | ||
"Framework :: Celery", | ||
] | ||
packages = [ | ||
{ include = "celery_signals", from = "src" } | ||
] | ||
|
||
[tool.poetry.dependencies] | ||
python = "^3.9" | ||
Django = "^4.0" | ||
celery = "^5.3" | ||
django-stubs = "^4.2.4" | ||
pytest-cov = "^4.1.0" | ||
setuptools = "^68.2.2" | ||
django-unified-signals = "^0.1.1" | ||
|
||
[tool.poetry.group.dev.dependencies] | ||
black = "^23.3.0" | ||
botocore = "^1.31.49" | ||
boto3 = "^1.28.49" | ||
ipython = "^8.14.0" | ||
ipdb = "^0.13.13" | ||
liccheck = "^0.9.1" | ||
pytest-django = "^4.5.2" | ||
pytest-watch = "^4.2.0" | ||
safety = "^2.3.5" | ||
checkov = "^2.4.41" | ||
|
||
[tool.mypy] | ||
plugins = [ | ||
"mypy_django_plugin.main" | ||
] | ||
|
||
[tool.django-stubs] | ||
django_settings_module = "tests.testapp.settings" | ||
|
||
[build-system] | ||
requires = ["poetry-core"] | ||
build-backend = "poetry.core.masonry.api" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
[pytest] | ||
DJANGO_SETTINGS_MODULE = tests.testapp.settings | ||
python_files = tests.py test_*.py *_tests.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .receivers import receiver_task |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import importlib | ||
import json | ||
import typing | ||
from functools import wraps | ||
|
||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
from django.dispatch import receiver | ||
from unified_signals import UnifiedSignal | ||
|
||
|
||
def get_celery_app(): | ||
try: | ||
app_path: str = settings.EVENT_SIGNALS_CELERY_APP | ||
except AttributeError: | ||
raise ImproperlyConfigured( | ||
"EVENT_SIGNALS_CELERY_APP setting is not defined. " | ||
"This should point to the celery app object " | ||
"in the module (e.g. project.celery.app)" | ||
) | ||
else: | ||
try: | ||
module, app_name = app_path.rsplit(".", 1) | ||
except ValueError: | ||
raise ImproperlyConfigured( | ||
"EVENT_SIGNALS_CELERY_APP should point " | ||
"to the celery app object in the module " | ||
"(e.g. project.celery.app)" | ||
) | ||
return getattr(importlib.import_module(module), app_name) | ||
|
||
|
||
app = get_celery_app() | ||
|
||
|
||
def receiver_task( | ||
signal: UnifiedSignal, # TODO: also accept multiple signals as original Signal does | ||
celery_task_options: typing.Optional[typing.Dict] = None, | ||
**options, | ||
): | ||
if celery_task_options is None: | ||
celery_task_options = dict() | ||
|
||
def decorator(func): | ||
@wraps(func) | ||
def consumer_function(message_data: str = "{}", *args, **kwargs): | ||
message = signal.message_class(**json.loads(message_data)) | ||
return func(sender=None, message=message, *args, **kwargs) | ||
|
||
consumer = app.task(**celery_task_options)(consumer_function) | ||
app.register_task(consumer) | ||
|
||
def producer( | ||
signal=signal, | ||
sender=None, | ||
message: typing.Optional[typing.Any] = None, | ||
*_args, | ||
**_kwargs, | ||
): | ||
message_data = json.dumps(message.__dict__) if message else "{}" | ||
return consumer.delay(message_data, *_args, **_kwargs) | ||
|
||
signal.connect(producer, **options) | ||
|
||
return func | ||
|
||
return decorator |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import dataclasses | ||
from unittest import mock | ||
|
||
import pytest | ||
from django.conf import settings | ||
from django.core.exceptions import ImproperlyConfigured | ||
from django.test import override_settings | ||
from unified_signals import UnifiedSignal | ||
|
||
from celery_signals.receivers import get_celery_app, receiver_task | ||
|
||
|
||
@dataclasses.dataclass | ||
class DataMock: | ||
field: int | ||
|
||
|
||
class SenderMock: | ||
pass | ||
|
||
|
||
def test_celery_signal_receiver(): | ||
signal = UnifiedSignal(DataMock) | ||
|
||
@receiver_task(signal) | ||
def handle_signal(**kwargs): | ||
assert True | ||
|
||
signal.send(SenderMock(), DataMock(field=10)) | ||
|
||
|
||
@override_settings( | ||
CELERY_TASK_ALWAYS_EAGER=True, EVENT_SIGNALS_CELERY_APP="tests.testapp.celery.app" | ||
) | ||
def test_celery_signal_receiver_creates_celery_task(): | ||
signal = UnifiedSignal(DataMock) | ||
|
||
with mock.patch("tests.testapp.celery.app.register_task") as task_mock: | ||
|
||
@receiver_task(signal) | ||
def handle_signal(**kwargs): | ||
... | ||
|
||
signal.send(SenderMock(), DataMock(field=10)) | ||
task_mock.assert_called_once() | ||
|
||
|
||
@override_settings( | ||
CELERY_TASK_ALWAYS_EAGER=True, EVENT_SIGNALS_CELERY_APP="tests.testapp.celery.app" | ||
) | ||
def test_celery_signal_receiver_consumer_runs_receiver_function(): | ||
signal = UnifiedSignal(DataMock) | ||
|
||
@receiver_task(signal, weak=False) | ||
def handle_signal(sender, message, **kwargs): | ||
assert message.field == 10 | ||
assert message.__class__ == DataMock | ||
|
||
signal.send(SenderMock(), DataMock(field=10)) | ||
|
||
|
||
def test_receivers_import_without_celery_app_defined(): | ||
OLD_EVENT_SIGNALS_CELERY_APP = settings.EVENT_SIGNALS_CELERY_APP | ||
del settings.EVENT_SIGNALS_CELERY_APP | ||
|
||
with pytest.raises(ImproperlyConfigured): | ||
get_celery_app() | ||
|
||
settings.EVENT_SIGNALS_CELERY_APP = OLD_EVENT_SIGNALS_CELERY_APP | ||
|
||
|
||
def test_receivers_import_with_celery_app_defined_incorrectly(): | ||
OLD_EVENT_SIGNALS_CELERY_APP = settings.EVENT_SIGNALS_CELERY_APP | ||
settings.EVENT_SIGNALS_CELERY_APP = "bad_import" | ||
|
||
with pytest.raises(ImproperlyConfigured): | ||
get_celery_app() | ||
|
||
settings.EVENT_SIGNALS_CELERY_APP = OLD_EVENT_SIGNALS_CELERY_APP |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import logging | ||
import os | ||
|
||
from celery import Celery | ||
|
||
# Set the default Django settings module for the 'celery' program. | ||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") | ||
|
||
app = Celery("project") | ||
|
||
# Using a string here means the worker doesn't have to serialize | ||
# the configuration object to child processes. | ||
# - namespace='CELERY' means all celery-related configuration keys | ||
# should have a `CELERY_` prefix. | ||
app.config_from_object("django.conf:settings", namespace="CELERY") | ||
|
||
# Load task modules from all registered Django apps. | ||
app.autodiscover_tasks() | ||
|
||
|
||
logger = logging.getLogger(__file__) | ||
|
||
|
||
@app.task(bind=True, ignore_result=True) | ||
def debug_task(self): | ||
logger.info("PING") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# minimal settings for running tests | ||
|
||
SECRET_KEY = "Some secret key" | ||
|
||
# CELERY_ALWAYS_EAGER = True | ||
|
||
EVENT_SIGNALS_CELERY_APP = "tests.testapp.celery.app" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
[tox] | ||
isolated_build = true | ||
envlist = | ||
black | ||
safety | ||
liccheck | ||
mypy | ||
coverage | ||
py{3.9,3.10,3.11}-dj{4.0,4.1,4.2} | ||
|
||
[testenv] | ||
allowlist_externals = poetry | ||
deps = | ||
coverage | ||
commands_pre = | ||
poetry install | ||
poetry install --no-root --sync | ||
dj4.0: pip install Django>=4.0,<4.1 | ||
dj4.1: pip install Django>=4.1,<4.2 | ||
dj4.2: pip install Django>=4.2,<4.3 | ||
commands = | ||
poetry run python manage.py --version | ||
poetry run pytest --cov=src/celery_signals tests/ | ||
|
||
|
||
[testenv:safety] | ||
basepython = python3.11 | ||
deps = safety | ||
commands = safety check | ||
|
||
|
||
[testenv:mypy] | ||
basepython = python3.11 | ||
commands = | ||
poetry run mypy tests src/celery_signals | ||
|
||
|
||
[testenv:black] | ||
basepython = python3.11 | ||
commands = | ||
black --check tests src/celery_signals | ||
|
||
|
||
[testenv:liccheck] | ||
basepython = python3.11 | ||
deps = liccheck | ||
commands = | ||
poetry export -f requirements.txt --output {envtmpdir}/requirements.txt | ||
liccheck -r {envtmpdir}/requirements.txt -l PARANOID | ||
|
||
|
||
[testenv:coverage] | ||
basepython = python3.11 | ||
commands_pre = | ||
poetry install | ||
poetry install --no-root --sync | ||
commands = | ||
poetry run pytest --cov=src/celery_signals tests/ |