mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-12-06 04:41:41 +01:00
Compare commits
6 Commits
535bdd743b
...
bd56966a18
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd56966a18 | ||
|
|
f5ddbb8004 | ||
|
|
c45d5d7325 | ||
|
|
c679ec0646 | ||
|
|
69a51bb08a | ||
|
|
0dd47e72bc |
@ -25,12 +25,12 @@ exclude: |
|
|||||||
repos:
|
repos:
|
||||||
# Code Upgrades
|
# Code Upgrades
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v3.21.0
|
rev: v3.21.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py38-plus]
|
args: [--py38-plus]
|
||||||
- repo: https://github.com/adamchainz/django-upgrade
|
- repo: https://github.com/adamchainz/django-upgrade
|
||||||
rev: 1.29.0
|
rev: 1.29.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: django-upgrade
|
- id: django-upgrade
|
||||||
args: [--target-version=4.2]
|
args: [--target-version=4.2]
|
||||||
@ -64,7 +64,7 @@ repos:
|
|||||||
- id: check-executables-have-shebangs
|
- id: check-executables-have-shebangs
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||||
rev: 3.4.0
|
rev: 3.4.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: editorconfig-checker
|
- id: editorconfig-checker
|
||||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||||
@ -76,7 +76,7 @@ repos:
|
|||||||
- --disable=MD013
|
- --disable=MD013
|
||||||
# Infrastructure
|
# Infrastructure
|
||||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||||
rev: v2.11.0
|
rev: v2.11.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyproject-fmt
|
- id: pyproject-fmt
|
||||||
name: pyproject.toml formatter
|
name: pyproject.toml formatter
|
||||||
|
|||||||
@ -5,7 +5,7 @@ manage online service access.
|
|||||||
# This will make sure the app is always imported when
|
# This will make sure the app is always imported when
|
||||||
# Django starts so that shared_task will use this app.
|
# Django starts so that shared_task will use this app.
|
||||||
|
|
||||||
__version__ = '4.11.0'
|
__version__ = '4.11.2'
|
||||||
__title__ = 'Alliance Auth'
|
__title__ = 'Alliance Auth'
|
||||||
__title_useragent__ = 'AllianceAuth'
|
__title_useragent__ = 'AllianceAuth'
|
||||||
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
__url__ = 'https://gitlab.com/allianceauth/allianceauth'
|
||||||
|
|||||||
@ -727,7 +727,8 @@ class TestEveSwaggerProvider(TestCase):
|
|||||||
my_provider = EveSwaggerProvider()
|
my_provider = EveSwaggerProvider()
|
||||||
my_client = my_provider.client
|
my_client = my_provider.client
|
||||||
operation = my_client.Universe.get_universe_factions()
|
operation = my_client.Universe.get_universe_factions()
|
||||||
self.assertEqual(
|
expected_variants = {
|
||||||
operation.future.request.headers['User-Agent'],
|
f'AllianceAuth/{aa_version} (dummy@example.net; +{aa_url}) DjangoEsi/{esi_version} (+{esi_url})', # Django-ESI 8.0.0
|
||||||
f'AllianceAuth/{aa_version} (dummy@example.net; +{aa_url}) Django-ESI/{esi_version} (+{esi_url})'
|
f'AllianceAuth/{aa_version} (dummy@example.net; +{aa_url}) Django-ESI/{esi_version} (+{esi_url})' # Django-ESI 7.x, Py38 Py39
|
||||||
)
|
}
|
||||||
|
self.assertIn(operation.future.request.headers['User-Agent'], expected_variants)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-09-21 13:44+1000\n"
|
"POT-Creation-Date: 2025-11-13 10:19+1000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -57,7 +57,7 @@ msgid "You are not allowed to add or remove these restricted groups: %s"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:72
|
#: allianceauth/authentication/models.py:72
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:104
|
#: allianceauth/project_template/project_name/settings/base.py:105
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -66,57 +66,57 @@ msgid "Czech"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:74
|
#: allianceauth/authentication/models.py:74
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:106
|
#: allianceauth/project_template/project_name/settings/base.py:107
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:75
|
#: allianceauth/authentication/models.py:75
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:107
|
#: allianceauth/project_template/project_name/settings/base.py:108
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:76
|
#: allianceauth/authentication/models.py:76
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:108
|
#: allianceauth/project_template/project_name/settings/base.py:109
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:77
|
#: allianceauth/authentication/models.py:77
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:109
|
#: allianceauth/project_template/project_name/settings/base.py:110
|
||||||
msgid "Japanese"
|
msgid "Japanese"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:78
|
#: allianceauth/authentication/models.py:78
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:110
|
#: allianceauth/project_template/project_name/settings/base.py:111
|
||||||
msgid "Korean"
|
msgid "Korean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:79
|
#: allianceauth/authentication/models.py:79
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:111
|
#: allianceauth/project_template/project_name/settings/base.py:112
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:80
|
#: allianceauth/authentication/models.py:80
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:114
|
#: allianceauth/project_template/project_name/settings/base.py:115
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:81
|
#: allianceauth/authentication/models.py:81
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:112
|
#: allianceauth/project_template/project_name/settings/base.py:113
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:82
|
#: allianceauth/authentication/models.py:82
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:113
|
#: allianceauth/project_template/project_name/settings/base.py:114
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:83
|
#: allianceauth/authentication/models.py:83
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:115
|
#: allianceauth/project_template/project_name/settings/base.py:116
|
||||||
msgid "Ukrainian"
|
msgid "Ukrainian"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:84
|
#: allianceauth/authentication/models.py:84
|
||||||
#: allianceauth/project_template/project_name/settings/base.py:116
|
#: allianceauth/project_template/project_name/settings/base.py:117
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -125,22 +125,30 @@ msgstr ""
|
|||||||
msgid "Language"
|
msgid "Language"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:105
|
#: allianceauth/authentication/models.py:106
|
||||||
#: allianceauth/templates/allianceauth/night-toggle.html:6
|
#: allianceauth/templates/allianceauth/night-toggle.html:6
|
||||||
msgid "Night Mode"
|
msgid "Night Mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:109
|
#: allianceauth/authentication/models.py:110
|
||||||
#: allianceauth/theme/templates/theme/theme_select.html:4
|
#: allianceauth/theme/templates/theme/theme_select.html:4
|
||||||
msgid "Theme"
|
msgid "Theme"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:126
|
#: allianceauth/authentication/models.py:117
|
||||||
|
msgid "Minimize Sidebar Menu"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/authentication/models.py:119
|
||||||
|
msgid "Keep the sidebar menu minimized"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/authentication/models.py:133
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "State changed to: %s"
|
msgid "State changed to: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/authentication/models.py:127
|
#: allianceauth/authentication/models.py:134
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your user's state is now: %(state)s"
|
msgid "Your user's state is now: %(state)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -200,8 +208,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: allianceauth/authentication/templates/authentication/tokens.html:7
|
#: allianceauth/authentication/templates/authentication/tokens.html:7
|
||||||
#: allianceauth/authentication/templates/authentication/tokens.html:11
|
#: allianceauth/authentication/templates/authentication/tokens.html:11
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:133
|
#: allianceauth/menu/templates/menu/menu-user.html:158
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:136
|
#: allianceauth/menu/templates/menu/menu-user.html:161
|
||||||
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:62
|
#: allianceauth/templates/allianceauth/top-menu-user-dropdown.html:62
|
||||||
msgid "Token Management"
|
msgid "Token Management"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -747,8 +755,8 @@ msgstr ""
|
|||||||
#: allianceauth/fleetactivitytracking/views.py:323
|
#: allianceauth/fleetactivitytracking/views.py:323
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot register the fleet participation for {character.character_name}. The "
|
"Cannot register the fleet participation for {character_name}. The character "
|
||||||
"character needs to be online."
|
"needs to be online."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/framework/apps.py:16
|
#: allianceauth/framework/apps.py:16
|
||||||
@ -1486,37 +1494,45 @@ msgid "Notifications"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:77
|
#: allianceauth/menu/templates/menu/menu-user.html:77
|
||||||
|
msgid "Sidebar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/menu/templates/menu/menu-user.html:93
|
||||||
|
msgid "Minimize Sidebar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: allianceauth/menu/templates/menu/menu-user.html:102
|
||||||
msgid "Super User"
|
msgid "Super User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:83
|
#: allianceauth/menu/templates/menu/menu-user.html:108
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:86
|
#: allianceauth/menu/templates/menu/menu-user.html:111
|
||||||
msgid "Alliance Auth Documentation"
|
msgid "Alliance Auth Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:94
|
#: allianceauth/menu/templates/menu/menu-user.html:119
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:97
|
#: allianceauth/menu/templates/menu/menu-user.html:122
|
||||||
msgid "Alliance Auth Discord"
|
msgid "Alliance Auth Discord"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:105
|
#: allianceauth/menu/templates/menu/menu-user.html:130
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:108
|
#: allianceauth/menu/templates/menu/menu-user.html:133
|
||||||
msgid "Alliance Auth Git"
|
msgid "Alliance Auth Git"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:118
|
#: allianceauth/menu/templates/menu/menu-user.html:143
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:121
|
#: allianceauth/menu/templates/menu/menu-user.html:146
|
||||||
#: allianceauth/templates/allianceauth/top-menu-admin.html:9
|
#: allianceauth/templates/allianceauth/top-menu-admin.html:9
|
||||||
msgid "Admin"
|
msgid "Admin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:144
|
#: allianceauth/menu/templates/menu/menu-user.html:169
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:147
|
#: allianceauth/menu/templates/menu/menu-user.html:172
|
||||||
msgid "Sign Out"
|
msgid "Sign Out"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:155
|
#: allianceauth/menu/templates/menu/menu-user.html:180
|
||||||
#: allianceauth/menu/templates/menu/menu-user.html:158
|
#: allianceauth/menu/templates/menu/menu-user.html:183
|
||||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:13
|
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:13
|
||||||
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:14
|
#: allianceauth/templates/allianceauth/top-menu-rh-default.html:14
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
@ -1777,9 +1793,9 @@ msgstr ""
|
|||||||
msgid "That service account already exists"
|
msgid "That service account already exists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/services/abstract.py:103
|
#: allianceauth/services/abstract.py:105
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Successfully set your {self.service_name} password"
|
msgid "Successfully set your {service_name} password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/services/apps.py:8 allianceauth/services/auth_hooks.py:12
|
#: allianceauth/services/apps.py:8 allianceauth/services/auth_hooks.py:12
|
||||||
@ -2318,11 +2334,11 @@ msgstr ""
|
|||||||
msgid "Invalid Link. Please use zkillboard.com or kb.evetools.org"
|
msgid "Invalid Link. Please use zkillboard.com or kb.evetools.org"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/srp/form.py:46
|
#: allianceauth/srp/form.py:49
|
||||||
msgid "Invalid Link. Please post a direct link to a killmail."
|
msgid "Invalid Link. Please post a direct link to a killmail."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/srp/form.py:53
|
#: allianceauth/srp/form.py:56
|
||||||
msgid "After Action Report Link"
|
msgid "After Action Report Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2596,7 +2612,7 @@ msgstr ""
|
|||||||
msgid "Saved changes to SRP fleet %(fleetname)s"
|
msgid "Saved changes to SRP fleet %(fleetname)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/templates/allianceauth/admin-status/esi_check.html:4
|
#: allianceauth/templates/allianceauth/admin-status/esi_check.html:5
|
||||||
msgid "Your Server received an ESI error response code of "
|
msgid "Your Server received an ESI error response code of "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -3001,36 +3017,36 @@ msgstr ""
|
|||||||
msgid "Saved changes to the timer."
|
msgid "Saved changes to the timer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:55
|
#: allianceauth/views.py:78
|
||||||
msgid "Bad Request"
|
msgid "Bad Request"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:57 allianceauth/views.py:87
|
#: allianceauth/views.py:80 allianceauth/views.py:110
|
||||||
msgid ""
|
msgid ""
|
||||||
"Auth encountered an error processing your request, please try again. If the "
|
"Auth encountered an error processing your request, please try again. If the "
|
||||||
"error persists, please contact the administrators."
|
"error persists, please contact the administrators."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:65
|
#: allianceauth/views.py:88
|
||||||
msgid "Permission Denied"
|
msgid "Permission Denied"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:67
|
#: allianceauth/views.py:90
|
||||||
msgid ""
|
msgid ""
|
||||||
"You do not have permission to access the requested page. If you believe this "
|
"You do not have permission to access the requested page. If you believe this "
|
||||||
"is in error please contact the administrators."
|
"is in error please contact the administrators."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:75
|
#: allianceauth/views.py:98
|
||||||
msgid "Page Not Found"
|
msgid "Page Not Found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:77
|
#: allianceauth/views.py:100
|
||||||
msgid ""
|
msgid ""
|
||||||
"Page does not exist. If you believe this is in error please contact the "
|
"Page does not exist. If you believe this is in error please contact the "
|
||||||
"administrators. "
|
"administrators. "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: allianceauth/views.py:85
|
#: allianceauth/views.py:108
|
||||||
msgid "Internal Server Error"
|
msgid "Internal Server Error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|||||||
@ -26,7 +26,7 @@ app.conf.task_default_priority = 5 # anything called with the task.delay() will
|
|||||||
app.conf.worker_prefetch_multiplier = 1 # only prefetch single tasks at a time on the workers so that prio tasks happen
|
app.conf.worker_prefetch_multiplier = 1 # only prefetch single tasks at a time on the workers so that prio tasks happen
|
||||||
|
|
||||||
app.conf.ONCE = {
|
app.conf.ONCE = {
|
||||||
'backend': 'allianceauth.services.tasks.DjangoBackend',
|
'backend': 'allianceauth.services.celery_once.backends.DjangoBackend',
|
||||||
'settings': {}
|
'settings': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
allianceauth/services/celery_once/__init__.py
Normal file
0
allianceauth/services/celery_once/__init__.py
Normal file
19
allianceauth/services/celery_once/backends.py
Normal file
19
allianceauth/services/celery_once/backends.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from celery_once import AlreadyQueued
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
|
||||||
|
class DjangoBackend:
|
||||||
|
"""Locking backend for celery once."""
|
||||||
|
|
||||||
|
def __init__(self, settings):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def raise_or_lock(key, timeout):
|
||||||
|
acquired = cache.add(key=key, value="lock", timeout=timeout)
|
||||||
|
if not acquired:
|
||||||
|
raise AlreadyQueued(int(cache.ttl(key)))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_lock(key):
|
||||||
|
return cache.delete(key)
|
||||||
8
allianceauth/services/celery_once/tasks.py
Normal file
8
allianceauth/services/celery_once/tasks.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from celery_once import QueueOnce as BaseTask
|
||||||
|
|
||||||
|
|
||||||
|
class QueueOnce(BaseTask):
|
||||||
|
"""QueueOnce class with custom defaults."""
|
||||||
|
|
||||||
|
once = BaseTask.once
|
||||||
|
once["graceful"] = True
|
||||||
47
allianceauth/services/celery_once/tests.py
Normal file
47
allianceauth/services/celery_once/tests.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
from celery_once import AlreadyQueued
|
||||||
|
from django.core.cache import cache
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
from allianceauth.services.celery_once.backends import DjangoBackend
|
||||||
|
|
||||||
|
|
||||||
|
class TestDjangoBackend(TestCase):
|
||||||
|
TEST_KEY = "my-django-backend-test-key"
|
||||||
|
TIMEOUT = 1800
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
cache.delete(self.TEST_KEY)
|
||||||
|
self.backend = DjangoBackend(dict())
|
||||||
|
|
||||||
|
def test_can_get_lock(self):
|
||||||
|
"""
|
||||||
|
when lock can be acquired
|
||||||
|
then set it with timeout
|
||||||
|
"""
|
||||||
|
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||||
|
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
||||||
|
self.assertAlmostEqual(cache.ttl(self.TEST_KEY), self.TIMEOUT, delta=2)
|
||||||
|
|
||||||
|
def test_when_cant_get_lock_raise_exception(self):
|
||||||
|
"""
|
||||||
|
when lock can bot be acquired
|
||||||
|
then raise AlreadyQueued exception with countdown
|
||||||
|
"""
|
||||||
|
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||||
|
except Exception as ex:
|
||||||
|
self.assertIsInstance(ex, AlreadyQueued)
|
||||||
|
self.assertAlmostEqual(ex.countdown, self.TIMEOUT, delta=2)
|
||||||
|
|
||||||
|
def test_can_clear_lock(self):
|
||||||
|
"""
|
||||||
|
when a lock exists
|
||||||
|
then can get a new lock after clearing it
|
||||||
|
"""
|
||||||
|
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||||
|
|
||||||
|
self.backend.clear_lock(self.TEST_KEY)
|
||||||
|
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
||||||
|
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
||||||
@ -3,33 +3,11 @@ import logging
|
|||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from .hooks import ServicesHook
|
from .hooks import ServicesHook
|
||||||
from celery_once import QueueOnce as BaseTask, AlreadyQueued
|
from .celery_once.tasks import QueueOnce # noqa: F401 - for backwards compatibility
|
||||||
from django.core.cache import cache
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class QueueOnce(BaseTask):
|
|
||||||
once = BaseTask.once
|
|
||||||
once['graceful'] = True
|
|
||||||
|
|
||||||
|
|
||||||
class DjangoBackend:
|
|
||||||
def __init__(self, settings):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def raise_or_lock(key, timeout):
|
|
||||||
acquired = cache.add(key=key, value="lock", timeout=timeout)
|
|
||||||
if not acquired:
|
|
||||||
raise AlreadyQueued(int(cache.ttl(key)))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def clear_lock(key):
|
|
||||||
return cache.delete(key)
|
|
||||||
|
|
||||||
|
|
||||||
@shared_task(bind=True)
|
@shared_task(bind=True)
|
||||||
def validate_services(self, pk):
|
def validate_services(self, pk):
|
||||||
user = User.objects.get(pk=pk)
|
user = User.objects.get(pk=pk)
|
||||||
@ -38,7 +16,7 @@ def validate_services(self, pk):
|
|||||||
for svc in ServicesHook.get_services():
|
for svc in ServicesHook.get_services():
|
||||||
try:
|
try:
|
||||||
svc.validate_user(user)
|
svc.validate_user(user)
|
||||||
except:
|
except Exception:
|
||||||
logger.exception(f'Exception running validate_user for services module {svc} on user {user}')
|
logger.exception(f'Exception running validate_user for services module {svc} on user {user}')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,10 @@
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from celery_once import AlreadyQueued
|
|
||||||
|
|
||||||
from django.core.cache import cache
|
|
||||||
from django.test import override_settings, TestCase
|
from django.test import override_settings, TestCase
|
||||||
|
|
||||||
from allianceauth.tests.auth_utils import AuthUtils
|
from allianceauth.tests.auth_utils import AuthUtils
|
||||||
from allianceauth.services.tasks import validate_services, update_groups_for_user
|
from allianceauth.services.tasks import validate_services, update_groups_for_user
|
||||||
|
|
||||||
from ..tasks import DjangoBackend
|
|
||||||
|
|
||||||
|
|
||||||
@override_settings(CELERY_ALWAYS_EAGER=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True)
|
@override_settings(CELERY_ALWAYS_EAGER=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True)
|
||||||
class ServicesTasksTestCase(TestCase):
|
class ServicesTasksTestCase(TestCase):
|
||||||
@ -46,46 +41,3 @@ class ServicesTasksTestCase(TestCase):
|
|||||||
self.assertTrue(svc.update_groups.called)
|
self.assertTrue(svc.update_groups.called)
|
||||||
args, _ = svc.update_groups.call_args
|
args, _ = svc.update_groups.call_args
|
||||||
self.assertEqual(self.member, args[0]) # Assert correct user
|
self.assertEqual(self.member, args[0]) # Assert correct user
|
||||||
|
|
||||||
|
|
||||||
class TestDjangoBackend(TestCase):
|
|
||||||
|
|
||||||
TEST_KEY = "my-django-backend-test-key"
|
|
||||||
TIMEOUT = 1800
|
|
||||||
|
|
||||||
def setUp(self) -> None:
|
|
||||||
cache.delete(self.TEST_KEY)
|
|
||||||
self.backend = DjangoBackend(dict())
|
|
||||||
|
|
||||||
def test_can_get_lock(self):
|
|
||||||
"""
|
|
||||||
when lock can be acquired
|
|
||||||
then set it with timetout
|
|
||||||
"""
|
|
||||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
|
||||||
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
|
||||||
self.assertAlmostEqual(cache.ttl(self.TEST_KEY), self.TIMEOUT, delta=2)
|
|
||||||
|
|
||||||
def test_when_cant_get_lock_raise_exception(self):
|
|
||||||
"""
|
|
||||||
when lock can bot be acquired
|
|
||||||
then raise AlreadyQueued exception with countdown
|
|
||||||
"""
|
|
||||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
|
||||||
except Exception as ex:
|
|
||||||
self.assertIsInstance(ex, AlreadyQueued)
|
|
||||||
self.assertAlmostEqual(ex.countdown, self.TIMEOUT, delta=2)
|
|
||||||
|
|
||||||
def test_can_clear_lock(self):
|
|
||||||
"""
|
|
||||||
when a lock exists
|
|
||||||
then can get a new lock after clearing it
|
|
||||||
"""
|
|
||||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
|
||||||
|
|
||||||
self.backend.clear_lock(self.TEST_KEY)
|
|
||||||
self.backend.raise_or_lock(self.TEST_KEY, self.TIMEOUT)
|
|
||||||
self.assertIsNotNone(cache.get(self.TEST_KEY))
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
PROTOCOL=https://
|
PROTOCOL=https://
|
||||||
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
|
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
|
||||||
DOMAIN=%DOMAIN%
|
DOMAIN=%DOMAIN%
|
||||||
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.11.0
|
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v4.11.2
|
||||||
|
|
||||||
# Nginx Proxy Manager
|
# Nginx Proxy Manager
|
||||||
PROXY_HTTP_PORT=80
|
PROXY_HTTP_PORT=80
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
FROM python:3.11-slim
|
FROM python:3.11-slim
|
||||||
ARG AUTH_VERSION=v4.11.0
|
ARG AUTH_VERSION=v4.11.2
|
||||||
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
|
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
|
||||||
ENV AUTH_USER=allianceauth
|
ENV AUTH_USER=allianceauth
|
||||||
ENV AUTH_GROUP=allianceauth
|
ENV AUTH_GROUP=allianceauth
|
||||||
|
|||||||
@ -26,7 +26,7 @@ app.conf.task_default_priority = 5 # anything called with the task.delay() will
|
|||||||
app.conf.worker_prefetch_multiplier = 1 # only prefetch single tasks at a time on the workers so that prio tasks happen
|
app.conf.worker_prefetch_multiplier = 1 # only prefetch single tasks at a time on the workers so that prio tasks happen
|
||||||
|
|
||||||
app.conf.ONCE = {
|
app.conf.ONCE = {
|
||||||
'backend': 'allianceauth.services.tasks.DjangoBackend',
|
'backend': 'allianceauth.services.celery_once.backends.DjangoBackend',
|
||||||
'settings': {}
|
'settings': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user