django-queuebie 0.6.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/workflows/quality-gate.yml +7 -7
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/workflows/release.yml +5 -5
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.gitignore +5 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.pre-commit-config.yaml +6 -5
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/CHANGES.md +12 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/CONTRIBUTING.md +3 -4
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/PKG-INFO +9 -9
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/conf.py +1 -6
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/getting-started.md +16 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/pyproject.toml +11 -9
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/__init__.py +1 -1
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/runner.py +14 -2
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/scripts/unix/install_requirements.sh +1 -1
- django_queuebie-0.7.1/scripts/windows/install_requirements.ps1 +2 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_runner.py +44 -0
- django_queuebie-0.6.0/scripts/windows/install_requirements.ps1 +0 -2
- django_queuebie-0.6.0/uv.lock +0 -1360
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.ambient-package-update/metadata.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.ambient-package-update/templates/snippets/content.tpl +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.ambient-package-update/templates/snippets/tagline.tpl +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.editorconfig +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.github/workflows/ci.yml +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/.readthedocs.yaml +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/CODE_OF_CONDUCT.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/LICENSE.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/MANIFEST.in +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/README.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/SECURITY.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/Makefile +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/changelog.rst +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/introduction.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/motivation.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/settings.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/features/setup.md +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/index.rst +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/docs/make.bat +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/manage.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/apps.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/database_blocker.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/exceptions.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/logger.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/management/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/management/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/management/commands/clear_queuebie_registry.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/messages.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/registry.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/settings.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/queuebie/utils.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/scripts/unix/publish_to_pypi.sh +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/scripts/windows/publish_to_pypi.ps1 +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/settings.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/commands/messages.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/commands/testapp.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/events/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/handlers/events/testapp.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/commands/messages.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/commands/my_commands.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/commands/other_commands.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/events/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/messages/events/my_events.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/handlers/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/handlers/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/handlers/commands/nested_domain.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/handlers/events/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/handlers/events/nested_domain.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/messages/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/messages/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/messages/commands/nested_commands.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/messages/events/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/nested_domain/messages/events/nested_events.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/handlers/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/handlers/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/handlers/commands/decoy.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/messages/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/messages/commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/tests/messages/commands/decoy_commands.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/testapp/urls.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/helpers/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/helpers/commands.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/helpers/events.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/management_commands/__init__.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/management_commands/test_clear_queuebie_registry.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_apps.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_database_blocker.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_exceptions.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_logger.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_messages.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_registry.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_settings.py +0 -0
- {django_queuebie-0.6.0 → django_queuebie-0.7.1}/tests/test_utils.py +0 -0
|
@@ -7,10 +7,10 @@ jobs:
|
|
|
7
7
|
linting:
|
|
8
8
|
runs-on: ubuntu-24.04
|
|
9
9
|
steps:
|
|
10
|
-
- uses: actions/checkout@
|
|
10
|
+
- uses: actions/checkout@v7
|
|
11
11
|
|
|
12
12
|
- name: Set up Python 3.14
|
|
13
|
-
uses: actions/setup-python@
|
|
13
|
+
uses: actions/setup-python@v7
|
|
14
14
|
with:
|
|
15
15
|
python-version: "3.14"
|
|
16
16
|
|
|
@@ -36,13 +36,13 @@ jobs:
|
|
|
36
36
|
django-version: 61
|
|
37
37
|
|
|
38
38
|
steps:
|
|
39
|
-
- uses: actions/checkout@
|
|
39
|
+
- uses: actions/checkout@v7
|
|
40
40
|
- name: setup python
|
|
41
|
-
uses: actions/setup-python@
|
|
41
|
+
uses: actions/setup-python@v7
|
|
42
42
|
with:
|
|
43
43
|
python-version: ${{ matrix.python-version }}
|
|
44
44
|
- name: Install uv
|
|
45
|
-
uses: astral-sh/setup-uv@
|
|
45
|
+
uses: astral-sh/setup-uv@v10.3.0
|
|
46
46
|
with:
|
|
47
47
|
cache-suffix: ${{ github.ref_type }}
|
|
48
48
|
- name: Install tox
|
|
@@ -64,9 +64,9 @@ jobs:
|
|
|
64
64
|
runs-on: ubuntu-24.04
|
|
65
65
|
needs: tests
|
|
66
66
|
steps:
|
|
67
|
-
- uses: actions/checkout@
|
|
67
|
+
- uses: actions/checkout@v7
|
|
68
68
|
|
|
69
|
-
- uses: actions/setup-python@
|
|
69
|
+
- uses: actions/setup-python@v7
|
|
70
70
|
with:
|
|
71
71
|
python-version: '3.14'
|
|
72
72
|
|
|
@@ -19,7 +19,7 @@ jobs:
|
|
|
19
19
|
outputs:
|
|
20
20
|
on-main: ${{ steps.check.outputs.on-main }}
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
23
|
with:
|
|
24
24
|
fetch-depth: 0
|
|
25
25
|
- name: Check if tag is on main
|
|
@@ -41,15 +41,15 @@ jobs:
|
|
|
41
41
|
permissions:
|
|
42
42
|
contents: read
|
|
43
43
|
steps:
|
|
44
|
-
- uses: actions/checkout@
|
|
44
|
+
- uses: actions/checkout@v7
|
|
45
45
|
|
|
46
46
|
- name: Set up Python 3.14
|
|
47
|
-
uses: actions/setup-python@
|
|
47
|
+
uses: actions/setup-python@v7
|
|
48
48
|
with:
|
|
49
49
|
python-version: "3.14"
|
|
50
50
|
|
|
51
51
|
- name: Install uv
|
|
52
|
-
uses: astral-sh/setup-uv@
|
|
52
|
+
uses: astral-sh/setup-uv@v10.3.0
|
|
53
53
|
|
|
54
54
|
- name: Build packages
|
|
55
55
|
run: uv build
|
|
@@ -76,7 +76,7 @@ jobs:
|
|
|
76
76
|
path: dist/
|
|
77
77
|
|
|
78
78
|
- name: Sign packages with Sigstore
|
|
79
|
-
uses: sigstore/gh-action-sigstore-python@v3.
|
|
79
|
+
uses: sigstore/gh-action-sigstore-python@v3.5.0
|
|
80
80
|
with:
|
|
81
81
|
inputs: >-
|
|
82
82
|
./dist/*.tar.gz
|
|
@@ -81,6 +81,11 @@ target/
|
|
|
81
81
|
profile_default/
|
|
82
82
|
ipython_config.py
|
|
83
83
|
|
|
84
|
+
# uv
|
|
85
|
+
# This is a library, so consumers never install from the lockfile. Not committing it avoids
|
|
86
|
+
# lockfile churn in every maintenance release.
|
|
87
|
+
uv.lock
|
|
88
|
+
|
|
84
89
|
# pdm
|
|
85
90
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
86
91
|
#pdm.lock
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
repos:
|
|
5
5
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
6
|
-
rev: v0.
|
|
6
|
+
rev: v0.17.1
|
|
7
7
|
hooks:
|
|
8
8
|
# Run the Ruff formatter.
|
|
9
9
|
- id: ruff-format
|
|
@@ -15,24 +15,25 @@ repos:
|
|
|
15
15
|
rev: 1.20.0
|
|
16
16
|
hooks:
|
|
17
17
|
- id: blacken-docs
|
|
18
|
+
args: [--line-length, "120"]
|
|
18
19
|
additional_dependencies:
|
|
19
|
-
- black==26.
|
|
20
|
+
- black==26.10.1
|
|
20
21
|
files: '(?:README\.md|\.ambient-package-update\/templates\/snippets\/.*\.tpl|docs\/.*\.(?:md|rst))'
|
|
21
22
|
|
|
22
23
|
- repo: https://github.com/asottile/pyupgrade
|
|
23
|
-
rev: v3.
|
|
24
|
+
rev: v3.22.0
|
|
24
25
|
hooks:
|
|
25
26
|
- id: pyupgrade
|
|
26
27
|
args: [ --py311-plus ]
|
|
27
28
|
|
|
28
29
|
- repo: https://github.com/adamchainz/django-upgrade
|
|
29
|
-
rev: 1.
|
|
30
|
+
rev: 1.33.0
|
|
30
31
|
hooks:
|
|
31
32
|
- id: django-upgrade
|
|
32
33
|
args: [--target-version, "5.2"]
|
|
33
34
|
|
|
34
35
|
- repo: https://github.com/adamchainz/djade-pre-commit
|
|
35
|
-
rev: 1.
|
|
36
|
+
rev: 1.10.0
|
|
36
37
|
hooks:
|
|
37
38
|
- id: djade
|
|
38
39
|
args: [--target-version, "5.2"]
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
**0.7.1** (2026-10-21)
|
|
4
|
+
* Updated the linting and CI setup to the current ambient-package-update template (ruff 0.17.1, `actions/checkout` v7, `actions/setup-python` v7)
|
|
5
|
+
* Fixed the Sphinx configuration for sphinx-rtd-theme 3, removing the documentation build warnings
|
|
6
|
+
* Fixed broken links in the pre-commit section of `CONTRIBUTING.md`
|
|
7
|
+
* Stopped committing `uv.lock`, since the package is a library and the lockfile never reaches its users
|
|
8
|
+
|
|
9
|
+
**0.7.0** (2026-10-05)
|
|
10
|
+
* `handle_message()` returns the handled messages in the order they were processed - the initial message(s)
|
|
11
|
+
followed by every command and event raised along the way - so the caller can tell whether its command led to the
|
|
12
|
+
expected event
|
|
13
|
+
* `handle_message()` no longer empties a list passed in by the caller
|
|
14
|
+
|
|
3
15
|
**0.6.0** (2026-09-09)
|
|
4
16
|
* Auto-discovery now walks the whole subtree of every local Django app, so `handlers/commands` and `handlers/events`
|
|
5
17
|
directories may live in sub-packages instead of only at the app root
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- Create a Python virtualenv and activate it
|
|
6
6
|
- Install "uv" with `pip install -U uv`
|
|
7
|
-
- Sync the requirements with `uv sync --
|
|
7
|
+
- Sync the requirements with `uv sync --extra dev`
|
|
8
8
|
|
|
9
9
|
## Add functionality
|
|
10
10
|
|
|
@@ -36,9 +36,8 @@ To enable the configured pre-push hooks, you need to [install](https://pre-commi
|
|
|
36
36
|
|
|
37
37
|
pre-commit install -t pre-push -t pre-commit --install-hooks
|
|
38
38
|
|
|
39
|
-
This will permanently install the git hooks
|
|
40
|
-
[`.
|
|
41
|
-
The hooks are configured in the [`.pre-commit-config.yaml`](templates/.pre-commit-config.yaml.tpl).
|
|
39
|
+
This will permanently install the git hooks in your local `.git/hooks` folder.
|
|
40
|
+
The hooks are configured in the [`.pre-commit-config.yaml`](./.pre-commit-config.yaml).
|
|
42
41
|
|
|
43
42
|
You can check whether hooks work as intended using the [run](https://pre-commit.com/#pre-commit-run) command:
|
|
44
43
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: django-queuebie
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: A simple and synchronous message queue for commands and events for Django
|
|
5
5
|
Project-URL: Homepage, https://github.com/ambient-innovation/django-queuebie/
|
|
6
6
|
Project-URL: Documentation, https://django-queuebie.readthedocs.io/en/latest/index.html
|
|
@@ -52,15 +52,15 @@ Requires-Dist: django>=5.2
|
|
|
52
52
|
Provides-Extra: dev
|
|
53
53
|
Requires-Dist: ambient-package-update; extra == 'dev'
|
|
54
54
|
Requires-Dist: keyring~=25.7; extra == 'dev'
|
|
55
|
-
Requires-Dist: pre-commit~=4.
|
|
56
|
-
Requires-Dist: pytest-cov~=7.
|
|
57
|
-
Requires-Dist: pytest-django~=4.
|
|
58
|
-
Requires-Dist: pytest-mock~=3.
|
|
55
|
+
Requires-Dist: pre-commit~=4.7; extra == 'dev'
|
|
56
|
+
Requires-Dist: pytest-cov~=7.1; extra == 'dev'
|
|
57
|
+
Requires-Dist: pytest-django~=4.14; extra == 'dev'
|
|
58
|
+
Requires-Dist: pytest-mock~=3.17; extra == 'dev'
|
|
59
59
|
Requires-Dist: sphinx-mdinclude~=0.6; extra == 'dev'
|
|
60
|
-
Requires-Dist: sphinx-rtd-theme~=3.
|
|
61
|
-
Requires-Dist: sphinx~=
|
|
62
|
-
Requires-Dist: typer~=0.
|
|
63
|
-
Requires-Dist: uv~=0.
|
|
60
|
+
Requires-Dist: sphinx-rtd-theme~=3.1; extra == 'dev'
|
|
61
|
+
Requires-Dist: sphinx~=8.2; extra == 'dev'
|
|
62
|
+
Requires-Dist: typer~=0.27; extra == 'dev'
|
|
63
|
+
Requires-Dist: uv~=0.13; extra == 'dev'
|
|
64
64
|
Description-Content-Type: text/markdown
|
|
65
65
|
|
|
66
66
|
[](https://pypi.org/project/django-queuebie/)
|
|
@@ -68,14 +68,9 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|
|
68
68
|
# a list of builtin themes.
|
|
69
69
|
html_theme = "sphinx_rtd_theme"
|
|
70
70
|
html_theme_options = {
|
|
71
|
-
"
|
|
71
|
+
"version_selector": False,
|
|
72
72
|
"style_external_links": False,
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
# Add any paths that contain custom static files (such as style sheets) here,
|
|
76
|
-
# relative to this directory. They are copied after the builtin static files,
|
|
77
|
-
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
78
|
-
html_static_path = ["_static"]
|
|
79
|
-
|
|
80
75
|
# Set master doc file
|
|
81
76
|
master_doc = "index"
|
|
@@ -102,3 +102,19 @@ handle_message(
|
|
|
102
102
|
)
|
|
103
103
|
)
|
|
104
104
|
```
|
|
105
|
+
|
|
106
|
+
`handle_message()` returns every message it handled, in the order they were processed: the message(s) you passed in,
|
|
107
|
+
followed by all commands and events the handlers returned along the way. Use it to find out what your command led to,
|
|
108
|
+
for example when a command handler can decide to do nothing and return `None`:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
handled = handle_message(BuyProduct(...))
|
|
112
|
+
|
|
113
|
+
if any(isinstance(message, ProductBought) for message in handled):
|
|
114
|
+
messages.success(request, "Thank you for your purchase.")
|
|
115
|
+
else:
|
|
116
|
+
messages.error(request, "The product could not be bought.")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The returned list tells you which handlers ran, not that their changes are committed. If you call `handle_message()`
|
|
120
|
+
inside an outer `transaction.atomic()` block, that outer transaction can still roll everything back.
|
|
@@ -37,15 +37,15 @@ dependencies = [
|
|
|
37
37
|
|
|
38
38
|
[project.optional-dependencies]
|
|
39
39
|
dev = [
|
|
40
|
-
'typer~=0.
|
|
41
|
-
'pytest-cov~=7.
|
|
42
|
-
'pytest-django~=4.
|
|
43
|
-
'pytest-mock~=3.
|
|
44
|
-
'pre-commit~=4.
|
|
45
|
-
'sphinx~=
|
|
46
|
-
'sphinx-rtd-theme~=3.
|
|
40
|
+
'typer~=0.27',
|
|
41
|
+
'pytest-cov~=7.1',
|
|
42
|
+
'pytest-django~=4.14',
|
|
43
|
+
'pytest-mock~=3.17',
|
|
44
|
+
'pre-commit~=4.7',
|
|
45
|
+
'sphinx~=8.2',
|
|
46
|
+
'sphinx-rtd-theme~=3.1',
|
|
47
47
|
'sphinx-mdinclude~=0.6',
|
|
48
|
-
'uv~=0.
|
|
48
|
+
'uv~=0.13',
|
|
49
49
|
'keyring~=25.7',
|
|
50
50
|
'ambient-package-update',
|
|
51
51
|
]
|
|
@@ -202,9 +202,11 @@ env_list = ["django52", "django60", "django61", ]
|
|
|
202
202
|
# Django deprecation overview: https://www.djangoproject.com/download/
|
|
203
203
|
package = "wheel"
|
|
204
204
|
wheel_build_env = ".pkg"
|
|
205
|
-
# This runner
|
|
205
|
+
# This runner installs via "uv sync" and ignores "deps", so every environment below
|
|
206
206
|
# installs its matrix Django version on top of the synced environment.
|
|
207
207
|
runner = "uv-venv-lock-runner"
|
|
208
|
+
# uv.lock is not committed for libraries, so tox resolves fresh instead of asserting a lockfile.
|
|
209
|
+
uv_sync_locked = false
|
|
208
210
|
extras = ["dev", ]
|
|
209
211
|
commands = [
|
|
210
212
|
["pytest", "--cov=queuebie", "--cov-report=term", "--cov-report=xml", "--ds", "settings", "tests"]
|
|
@@ -11,8 +11,16 @@ from queuebie.messages import Command, Event, Message
|
|
|
11
11
|
from queuebie.settings import get_queuebie_strict_mode
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def handle_message(messages: Message | list[Message]) ->
|
|
15
|
-
|
|
14
|
+
def handle_message(messages: Message | list[Message]) -> list[Message]:
|
|
15
|
+
"""
|
|
16
|
+
Process the given message(s) and every message their handlers return, until the queue is drained.
|
|
17
|
+
|
|
18
|
+
Returns all handled messages in the order they were processed - the initial message(s) first, followed by
|
|
19
|
+
everything raised along the way. The caller can inspect it to learn what its command led to, e.g. whether a
|
|
20
|
+
handler returned an event or bailed out with `None`.
|
|
21
|
+
"""
|
|
22
|
+
# Copy the input, so draining the queue doesn't empty the caller's list
|
|
23
|
+
queue: list[Message] = list(messages) if isinstance(messages, list) else [messages]
|
|
16
24
|
|
|
17
25
|
for message in queue:
|
|
18
26
|
if not isinstance(message, (Command, Event)):
|
|
@@ -21,9 +29,11 @@ def handle_message(messages: Message | list[Message]) -> None:
|
|
|
21
29
|
# Run auto-registry
|
|
22
30
|
message_registry.autodiscover()
|
|
23
31
|
|
|
32
|
+
handled: list[Message] = []
|
|
24
33
|
with transaction.atomic():
|
|
25
34
|
while queue:
|
|
26
35
|
message = queue.pop(0)
|
|
36
|
+
handled.append(message)
|
|
27
37
|
if isinstance(message, Command):
|
|
28
38
|
handler_list = message_registry.command_dict.get(message.module_path(), [])
|
|
29
39
|
block_db_access = False
|
|
@@ -34,6 +44,8 @@ def handle_message(messages: Message | list[Message]) -> None:
|
|
|
34
44
|
new_messages = _process_message(handler_list=handler_list, message=message, block_db_access=block_db_access)
|
|
35
45
|
queue.extend(new_messages)
|
|
36
46
|
|
|
47
|
+
return handled
|
|
48
|
+
|
|
37
49
|
|
|
38
50
|
def _process_message(*, handler_list: list, message: [Command, Event], block_db_access: bool) -> list[Message]:
|
|
39
51
|
"""
|
|
@@ -136,3 +136,47 @@ def test_handle_message_atomic_works(*args):
|
|
|
136
136
|
handle_message([CreateUser(username="username"), RaiseRuntimeError(error_msg="Something is broken.")])
|
|
137
137
|
|
|
138
138
|
assert User.objects.filter(username="username").exists() is False
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@pytest.mark.django_db
|
|
142
|
+
def test_handle_message_returns_handled_messages_in_order():
|
|
143
|
+
command = DoSomething(my_var=1)
|
|
144
|
+
|
|
145
|
+
handled = handle_message(messages=command)
|
|
146
|
+
|
|
147
|
+
assert len(handled) == 2 # noqa: PLR2004
|
|
148
|
+
assert handled[0] is command
|
|
149
|
+
assert isinstance(handled[1], SomethingHappened)
|
|
150
|
+
assert handled[1].other_var == 2 # noqa: PLR2004
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@pytest.mark.django_db
|
|
154
|
+
def test_handle_message_returns_only_initial_message_if_handler_returns_none():
|
|
155
|
+
command = CriticalCommand(my_var=1)
|
|
156
|
+
|
|
157
|
+
handled = handle_message(messages=command)
|
|
158
|
+
|
|
159
|
+
assert handled == [command]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@pytest.mark.django_db
|
|
163
|
+
def test_handle_message_returns_all_initial_messages_of_list():
|
|
164
|
+
command = DoSomething(my_var=1)
|
|
165
|
+
event = SomethingHappened(other_var=5)
|
|
166
|
+
|
|
167
|
+
handled = handle_message(messages=[command, event])
|
|
168
|
+
|
|
169
|
+
assert handled[0] is command
|
|
170
|
+
assert handled[1] is event
|
|
171
|
+
assert isinstance(handled[2], SomethingHappened)
|
|
172
|
+
assert handled[2].other_var == 2 # noqa: PLR2004
|
|
173
|
+
assert len(handled) == 3 # noqa: PLR2004
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@pytest.mark.django_db
|
|
177
|
+
def test_handle_message_does_not_empty_passed_list():
|
|
178
|
+
message_list = [CriticalCommand(my_var=1)]
|
|
179
|
+
|
|
180
|
+
handle_message(messages=message_list)
|
|
181
|
+
|
|
182
|
+
assert len(message_list) == 1
|