Compare commits

...

6 Commits

Author SHA1 Message Date
Joel Falknau
5e836c4285
pre-commit fixes 2024-12-04 22:08:47 +10:00
Joel Falknau
dc0c1a2818
collapse docker compose to make discord less unhappy 2024-12-04 21:33:48 +10:00
Joel Falknau
eaba01ad97
remove checks that have expired and bump others 2024-12-04 21:33:20 +10:00
Joel Falknau
f4c024d199
pre-commit fixes 2024-12-04 21:32:54 +10:00
Joel Falknau
8f4daea14f
sphinx theme v3 is now stable 2024-12-04 21:32:28 +10:00
Joel Falknau
b95f393a4c
update pre-commit 2024-12-04 21:31:16 +10:00
27 changed files with 122 additions and 177 deletions

View File

@ -5,20 +5,20 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.4
rev: v0.8.1
hooks:
# Run the linter, and only the linter
- id: ruff
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.21.0
rev: 1.22.2
hooks:
- id: django-upgrade
args: [--target-version=4.2]
# Formatting
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
# Identify invalid files
- id: check-ast
@ -75,14 +75,14 @@ repos:
swagger\.json
)
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.41.0
rev: v0.43.0
hooks:
- id: markdownlint
args:
- --disable=MD013
# Infrastructure
- repo: https://github.com/tox-dev/pyproject-fmt
rev: 2.2.3
rev: v2.5.0
hooks:
- id: pyproject-fmt
name: pyproject.toml formatter
@ -92,7 +92,7 @@ repos:
additional_dependencies:
- tox==4.18.1 # https://github.com/tox-dev/tox/releases/latest
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.19
rev: v0.23
hooks:
- id: validate-pyproject
name: Validate pyproject.toml

View File

@ -43,11 +43,12 @@ def system_package_redis(app_configs, **kwargs) -> list[CheckMessage]:
except InvalidVersion:
errors.append(Warning("Unable to confirm Redis Version"))
return errors
if redis_version.major == 7 and redis_version.minor == 2 and timezone.now() > timezone.datetime(year=2025, month=8, day=31, tzinfo=datetime.timezone.utc):
if redis_version.major == 7 and redis_version.minor == 4 and timezone.now() > timezone.datetime(year=2025, month=8, day=31, tzinfo=datetime.timezone.utc):
errors.append(Error(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A001"))
elif redis_version.major == 7 and redis_version.minor == 2:
errors.append(Error(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A019"))
elif redis_version.major == 7 and redis_version.minor == 0:
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A002"))
errors.append(Error(f"Redis {redis_version.public} EOL", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A019"))
elif redis_version.major == 6 and redis_version.minor == 2:
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://allianceauth.readthedocs.io/en/latest/installation/allianceauth.html#redis-and-other-tools", id="allianceauth.checks.A018"))
elif redis_version.major in [6, 5]:
@ -71,11 +72,7 @@ def system_package_mysql(app_configs, **kwargs) -> list[CheckMessage]:
# MySQL 8
if mysql_version.major == 8 and mysql_version.minor == 4 and timezone.now() > timezone.datetime(year=2032, month=4, day=30, tzinfo=datetime.timezone.utc):
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A004"))
elif mysql_version.major == 8 and mysql_version.minor == 3:
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A005"))
elif mysql_version.major == 8 and mysql_version.minor == 2:
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A006"))
elif mysql_version.major == 8 and mysql_version.minor == 1:
elif mysql_version.major == 8 and mysql_version.minor in [1, 2, 3]:
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A007"))
elif mysql_version.major == 8 and mysql_version.minor == 0 and timezone.now() > timezone.datetime(year=2026, month=4, day=30, tzinfo=datetime.timezone.utc):
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A008"))
@ -99,14 +96,7 @@ def system_package_mariadb(app_configs, **kwargs) -> list[CheckMessage]:
# MariaDB 11
if mariadb_version.major == 11 and mariadb_version.minor == 4 and timezone.now() > timezone.datetime(year=2029, month=5, day=19, tzinfo=datetime.timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A010"))
elif mariadb_version.major == 11 and mariadb_version.minor == 2:
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A018"))
if timezone.now() > timezone.datetime(year=2024, month=11, day=21, tzinfo=datetime.timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A011"))
elif mariadb_version.major == 11 and mariadb_version.minor == 1:
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A019"))
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A012"))
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 3]: # Demote versions down here once EOL
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 1, 2, 3, 5]: # Demote versions down here once EOL
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A013"))
# MariaDB 10

View File

@ -70,7 +70,7 @@ def forward(apps, schema_editor):
perm.delete()
def reverse(apps, schema_editor):
def reverse(apps, schema_editor): # noqa: C901
perm_dict = user_permissions_dict(apps)
corp_users = users_with_permission(apps, perm_dict['corpstats']['view_corp_corpstats'])

View File

@ -62,7 +62,7 @@ def corpstats_add(request, token):
@login_required
@user_passes_test(access_corpstats_test)
def corpstats_view(request, corp_id=None):
def corpstats_view(request, corp_id=None): # noqa: C901
corpstats = None
# get requested model

View File

@ -49,8 +49,8 @@ class EveFactionForm(EveEntityForm):
def clean_id(self):
try:
assert self.Meta.model.provider.get_faction(self.cleaned_data['id'])
except (AssertionError, ObjectNotFound):
raise EveEntityNotFoundError('faction', self.cleaned_data['id'])
except (AssertionError, ObjectNotFound) as e:
raise EveEntityNotFoundError('faction', self.cleaned_data['id']) from e
if self.Meta.model.objects.filter(faction_id=self.cleaned_data['id']).exists():
raise EveEntityExistsError('faction', self.cleaned_data['id'])
return self.cleaned_data['id']
@ -70,8 +70,8 @@ class EveCharacterForm(EveEntityForm):
def clean_id(self):
try:
assert self.Meta.model.provider.get_character(self.cleaned_data['id'])
except (AssertionError, ObjectNotFound):
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id'])
except (AssertionError, ObjectNotFound) as e:
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id']) from e
if self.Meta.model.objects.filter(character_id=self.cleaned_data['id']).exists():
raise EveEntityExistsError(self.entity_type_name, self.cleaned_data['id'])
return self.cleaned_data['id']
@ -90,8 +90,8 @@ class EveCorporationForm(EveEntityForm):
def clean_id(self):
try:
assert self.Meta.model.provider.get_corporation(self.cleaned_data['id'])
except (AssertionError, ObjectNotFound):
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id'])
except (AssertionError, ObjectNotFound) as e:
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id']) from e
if self.Meta.model.objects.filter(corporation_id=self.cleaned_data['id']).exists():
raise EveEntityExistsError(self.entity_type_name, self.cleaned_data['id'])
return self.cleaned_data['id']
@ -110,8 +110,8 @@ class EveAllianceForm(EveEntityForm):
def clean_id(self):
try:
assert self.Meta.model.provider.get_alliance(self.cleaned_data['id'])
except (AssertionError, ObjectNotFound):
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id'])
except (AssertionError, ObjectNotFound) as e:
raise EveEntityNotFoundError(self.entity_type_name, self.cleaned_data['id']) from e
if self.Meta.model.objects.filter(alliance_id=self.cleaned_data['id']).exists():
raise EveEntityExistsError(self.entity_type_name, self.cleaned_data['id'])
return self.cleaned_data['id']

View File

@ -223,8 +223,8 @@ class EveSwaggerProvider(EveProvider):
faction_id=data['faction_id'] if 'faction_id' in data else None,
)
return model
except HTTPNotFound:
raise ObjectNotFound(alliance_id, 'alliance')
except HTTPNotFound as e:
raise ObjectNotFound(alliance_id, 'alliance') from e
def get_corp(self, corp_id: int) -> Corporation:
"""Fetch corporation from ESI."""
@ -240,8 +240,8 @@ class EveSwaggerProvider(EveProvider):
faction_id=data['faction_id'] if 'faction_id' in data else None,
)
return model
except HTTPNotFound:
raise ObjectNotFound(corp_id, 'corporation')
except HTTPNotFound as e:
raise ObjectNotFound(corp_id, 'corporation') from e
def get_character(self, character_id: int) -> Character:
"""Fetch character from ESI."""
@ -256,8 +256,8 @@ class EveSwaggerProvider(EveProvider):
faction_id=affiliation['faction_id'] if 'faction_id' in affiliation else None,
)
return model
except (HTTPNotFound, HTTPUnprocessableEntity, ObjectNotFound):
raise ObjectNotFound(character_id, 'character')
except (HTTPNotFound, HTTPUnprocessableEntity, ObjectNotFound) as e:
raise ObjectNotFound(character_id, 'character') from e
def _fetch_character_name(self, character_id: int) -> str:
"""Fetch character name from ESI."""
@ -288,16 +288,16 @@ class EveSwaggerProvider(EveProvider):
return Entity(id=f['faction_id'], name=f['name'])
else:
raise KeyError()
except (HTTPNotFound, HTTPUnprocessableEntity, KeyError):
raise ObjectNotFound(faction_id, 'faction')
except (HTTPNotFound, HTTPUnprocessableEntity, KeyError) as e:
raise ObjectNotFound(faction_id, 'faction') from e
def get_itemtype(self, type_id: int) -> ItemType:
"""Fetch inventory item from ESI."""
try:
data = self.client.Universe.get_universe_types_type_id(type_id=type_id).result()
return ItemType(id=type_id, name=data['name'])
except (HTTPNotFound, HTTPUnprocessableEntity):
raise ObjectNotFound(type_id, 'type')
except (HTTPNotFound, HTTPUnprocessableEntity) as e:
raise ObjectNotFound(type_id, 'type') from e
provider = EveSwaggerProvider()

View File

@ -57,11 +57,11 @@ class EsiClientStub:
}
try:
return BravadoOperationStub(data[int(alliance_id)])
except KeyError:
except KeyError as e:
response = BravadoResponseStub(
404, f"Alliance with ID {alliance_id} not found"
)
raise HTTPNotFound(response)
raise HTTPNotFound(response) from e
@staticmethod
def get_alliances_alliance_id_corporations(alliance_id):
@ -87,11 +87,11 @@ class EsiClientStub:
}
try:
return BravadoOperationStub(data[int(character_id)])
except KeyError:
except KeyError as e:
response = BravadoResponseStub(
404, f"Character with ID {character_id} not found"
)
raise HTTPNotFound(response)
raise HTTPNotFound(response) from e
@staticmethod
def post_characters_affiliation(characters: list):
@ -147,11 +147,11 @@ class EsiClientStub:
}
try:
return BravadoOperationStub(data[int(corporation_id)])
except KeyError:
except KeyError as e:
response = BravadoResponseStub(
404, f"Corporation with ID {corporation_id} not found"
)
raise HTTPNotFound(response)
raise HTTPNotFound(response) from e
class Universe:
@staticmethod

View File

@ -143,7 +143,12 @@ def fatlink_statistics_corp_view(request, corpid, year=None, month=None):
@login_required
@permission_required('auth.fleetactivitytracking_statistics')
def fatlink_statistics_view(request, year=datetime.date.today().year, month=datetime.date.today().month):
def fatlink_statistics_view(request, year=None, month=None):
if year is None:
year = datetime.date.today().year
if month is None:
month = datetime.date.today().month
year = int(year)
month = int(month)
start_of_month = datetime.datetime(year, month, 1)
@ -176,9 +181,12 @@ def fatlink_statistics_view(request, year=datetime.date.today().year, month=date
@login_required
def fatlink_personal_statistics_view(request, year=datetime.date.today().year):
def fatlink_personal_statistics_view(request, year=None):
if year is None:
year = datetime.date.today().year
year = int(year)
logger.debug("Personal statistics view for year %i called by %s" % (year, request.user))
logger.debug(f"Personal statistics view for year {year} called by {request.user}")
user = request.user
logger.debug(f"fatlink_personal_statistics_view called by user {request.user}")

View File

@ -87,8 +87,8 @@ def group_membership_audit(request, group_id):
logger.warning(f"User {request.user} attempted to view the membership of group {group_id} but permission was denied")
raise PermissionDenied
except ObjectDoesNotExist:
raise Http404("Group does not exist")
except ObjectDoesNotExist as e:
raise Http404("Group does not exist") from e
render_items = {'group': group}
entries = RequestLog.objects.filter(group=group).order_by('-date')
render_items['entries'] = entries
@ -117,8 +117,8 @@ def group_membership_list(request, group_id):
)
raise PermissionDenied
except ObjectDoesNotExist:
raise Http404("Group does not exist")
except ObjectDoesNotExist as e:
raise Http404("Group does not exist") from e
group_leaders = group.authgroup.group_leaders.all()
members = []

View File

@ -111,8 +111,8 @@ def hr_application_view(request, app_id):
logger.debug(f"hr_application_view called by user {request.user} for app id {app_id}")
try:
app = Application.objects.prefetch_related('responses', 'comments', 'comments__user').get(pk=app_id)
except Application.DoesNotExist:
raise Http404
except Application.DoesNotExist as e:
raise Http404 from e
if request.method == 'POST':
if request.user.has_perm('hrapplications.add_applicationcomment'):
form = HRApplicationCommentForm(request.POST)

View File

@ -47,7 +47,7 @@ class MenuItem(models.Model):
)
# app related properties
hook_hash = models.CharField(
hook_hash = models.CharField( # noqa: DJ001
max_length=64,
default=None,
null=True,

View File

@ -77,7 +77,7 @@ class RenderedMenuItem:
self.html_id = hook_obj.html_id
def render_menu(request: HttpRequest) -> list[RenderedMenuItem]:
def render_menu(request: HttpRequest) -> list[RenderedMenuItem]: # noqa: C901
"""Return the rendered side menu for including in a template.
This function is creating BS5 style menus.

View File

@ -48,8 +48,8 @@ def permissions_audit(request, app_label, model, codename):
.prefetch_related('group_set', 'user_set', 'state_set',
'state_set__userprofile_set', 'group_set__user_set', 'state_set__userprofile_set__user')\
.get(content_type__app_label=app_label, content_type__model=model, codename=codename)
except Permission.DoesNotExist:
raise Http404
except Permission.DoesNotExist as e:
raise Http404 from e
context = {'permission': {
'permission': perm,

View File

@ -33,7 +33,6 @@ class AbstractServiceModel(models.Model):
related_name='%(app_label)s'
)
class Meta:
abstract = True
@ -85,8 +84,8 @@ class ServicesCRUDMixin(SingleObjectMixin):
try:
return queryset.get(user__pk=self.request.user.pk)
except ObjectDoesNotExist:
raise Http404
except ObjectDoesNotExist as e:
raise Http404 from e
class BaseDeactivateServiceAccountView(ServicesCRUDMixin, BaseServiceView, DeleteView):

View File

@ -44,26 +44,24 @@ MAX_JITTER_PER_RUN_SECS = 1.0
def worker(num: int):
"""worker function"""
worker_info = 'worker %d' % num
logger.info('%s: started', worker_info)
worker_info = f'worker {num}'
logger.info(f'{worker_info}: started')
client = DiscordClient(DISCORD_BOT_TOKEN)
try:
runs = 0
while runs < NUMBER_OF_RUNS:
run_info = '%s: run %d' % (worker_info, runs + 1)
run_info = f'{worker_info}: run {runs + 1}'
my_jitter_secs = random() * MAX_JITTER_PER_RUN_SECS
logger.info('%s - waiting %s secs', run_info, f'{my_jitter_secs:.3f}')
logger.info(f'{run_info} - waiting {my_jitter_secs:.3f} secs')
sleep(my_jitter_secs)
logger.info('%s - started', run_info)
logger.info(f'{run_info} - started')
try:
client.modify_guild_member(
DISCORD_GUILD_ID, DISCORD_USER_ID, nick=NICK
)
runs += 1
except DiscordApiBackoff as bo:
message = '%s - waiting out API backoff for %d ms' % (
run_info, bo.retry_after
)
message = f'{run_info} - waiting out API backoff for {bo.retry_after} ms'
logger.info(message)
print()
print(message)

View File

@ -89,12 +89,12 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
bo,
bo.retry_after_seconds
)
raise self.retry(countdown=bo.retry_after_seconds)
raise self.retry(exc=bo, countdown=bo.retry_after_seconds) from bo
except AttributeError:
raise ValueError(f'{method} not a valid method for DiscordUser')
except AttributeError as e:
raise ValueError(f'{method} not a valid method for DiscordUser') from e
except (HTTPError, ConnectionError):
except (HTTPError, ConnectionError) as e:
logger.warning(
'%s failed for user %s, retrying in %d secs',
method,
@ -103,7 +103,7 @@ def _task_perform_user_action(self, user_pk: int, method: str, **kwargs) -> None
exc_info=True
)
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
raise self.retry(exc=e, countdown=DISCORD_TASKS_RETRY_PAUSE) from e
else:
logger.error(
'%s failed for user %s after max retries',
@ -192,8 +192,8 @@ def _task_perform_users_action(self, method: str, **kwargs) -> Any:
try:
result = getattr(DiscordUser.objects, method)(**kwargs)
except AttributeError:
raise ValueError(f'{method} not a valid method for DiscordUser.objects')
except AttributeError as e:
raise ValueError(f'{method} not a valid method for DiscordUser.objects') from e
except DiscordApiBackoff as bo:
logger.info(
@ -202,9 +202,9 @@ def _task_perform_users_action(self, method: str, **kwargs) -> Any:
bo,
bo.retry_after_seconds
)
raise self.retry(countdown=bo.retry_after_seconds)
raise self.retry(exc=bo, countdown=bo.retry_after_seconds) from bo
except (HTTPError, ConnectionError):
except (HTTPError, ConnectionError)as e:
logger.warning(
'%s failed, retrying in %d secs',
method,
@ -212,7 +212,7 @@ def _task_perform_users_action(self, method: str, **kwargs) -> Any:
exc_info=True
)
if self.request.retries < DISCORD_TASKS_MAX_RETRIES:
raise self.retry(countdown=DISCORD_TASKS_RETRY_PAUSE)
raise self.retry(exc=e, countdown=DISCORD_TASKS_RETRY_PAUSE) from e
else:
logger.error('%s failed after max retries', method, exc_info=True)

View File

@ -52,7 +52,7 @@ class DiscourseTasks:
except Exception as e:
logger.exception(e)
logger.warning(f"Discourse group sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
logger.debug(f"Updated user {user} discourse groups.")
@staticmethod

View File

@ -41,9 +41,9 @@ class MumbleTasks:
return True
except MumbleUser.DoesNotExist:
logger.info(f"Mumble group sync failed for {user}, user does not have a mumble account")
except Exception:
except Exception as e:
logger.exception(f"Mumble group sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
else:
logger.debug(f"User {user} does not have a mumble account, skipping")
return False
@ -61,9 +61,9 @@ class MumbleTasks:
return True
except MumbleUser.DoesNotExist:
logger.info(f"Mumble display name sync failed for {user}, user does not have a mumble account")
except Exception:
except Exception as e:
logger.exception(f"Mumble display name sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
else:
logger.debug(f"User {user} does not have a mumble account, skipping")
return False

View File

@ -54,9 +54,9 @@ class OpenfireTasks:
logger.debug(f"Updating user {user} jabber groups to {groups}")
try:
OpenfireManager.update_user_groups(user.openfire.username, groups)
except Exception:
except Exception as e:
logger.exception(f"Jabber group sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
logger.debug(f"Updated user {user} jabber groups.")
else:
logger.debug("User does not have an openfire account")

View File

@ -8,10 +8,10 @@ class Phpbb3User(models.Model):
related_name='phpbb3')
username = models.CharField(max_length=254)
def __str__(self):
return self.username
class Meta:
permissions = (
("access_phpbb3", "Can access the phpBB3 service"),
)
def __str__(self) -> str:
return self.username

View File

@ -49,9 +49,9 @@ class Phpbb3Tasks:
logger.debug(f"Updating user {user} phpbb3 groups to {groups}")
try:
Phpbb3Manager.update_groups(user.phpbb3.username, groups)
except Exception:
except Exception as e:
logger.exception(f"Phpbb group sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
logger.debug(f"Updated user {user} phpbb3 groups.")
else:
logger.debug("User does not have a Phpbb3 account")

View File

@ -53,9 +53,9 @@ class SmfTasks:
logger.debug(f"Updating user {user} smf groups to {groups}")
try:
SmfManager.update_groups(user.smf.username, groups)
except Exception:
except Exception as e:
logger.exception(f"smf group sync failed for {user}, retrying in 10 mins")
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
logger.debug(f"Updated user {user} smf groups.")
else:
logger.debug("User does not have an smf account")
@ -77,11 +77,11 @@ class SmfTasks:
f"SMF displayed name sync failed for {user}, "
"user does not have a SMF account"
)
except Exception:
except Exception as e:
logger.exception(
f"SMF displayed name sync failed for {user}, retrying in 10 mins"
)
raise self.retry(countdown=60 * 10)
raise self.retry(exc=e, countdown=60 * 10) from e
else:
logger.debug(f"User {user} does not have a SMF account, skipping")

View File

@ -81,7 +81,7 @@ class Teamspeak3Tasks:
logger.debug(f"Updated user {user} teamspeak3 groups.")
except TeamspeakError as e:
logger.error(f"Error occured while syncing TS groups for {user}: {str(e)}")
raise self.retry(countdown=60*10)
raise self.retry(exc=e, countdown=60 * 10) from e
else:
logger.debug("User does not have a teamspeak3 account")

View File

@ -182,7 +182,7 @@ class TS3Proto:
"""
if isinstance(value, int):
return "%d" % value
return f"{value}"
value = value.replace("\\", r'\\')
for i, j in ts3_escape.items():
value = value.replace(i, j)
@ -197,7 +197,7 @@ class TS3Proto:
"""
if isinstance(value, int):
return "%d" % value
return f"{value}"
value = value.replace(r"\\", "\\")
for i, j in ts3_escape.items():
value = value.replace(j, i)

View File

@ -68,8 +68,8 @@ def m2m_changed_group_permissions(sender, instance, action, pk_set, *args, **kwa
logger.debug(f"Received m2m_changed from group {instance} permissions with action {action}")
if instance.pk and (action == "post_remove" or action == "post_clear"):
logger.debug(f"Checking if service permission changed for group {instance}")
# As validating an entire groups service could lead to many thousands of permission checks
# first we check that one of the permissions changed is, in fact, a service permission.
# As validating an entire group's service could lead to many thousands of permission checks,
# first, we check that one of the permissions changed is, in fact, a service permission.
perms = Permission.objects.filter(pk__in=pk_set)
got_change = False
service_perms = [svc.access_perm for svc in ServicesHook.get_services()]
@ -81,18 +81,19 @@ def m2m_changed_group_permissions(sender, instance, action, pk_set, *args, **kwa
continue
for svc in ServicesHook.get_services():
if svc.access_perm == path_perm:
logger.debug(f"Permissions changed for group {instance} on service {svc}, re-validating services for groups users")
logger.debug(f"Permissions changed for group {instance} on service {svc}, re-validating services for group users")
def validate_all_groups_users_for_service():
logger.debug(f"Performing validation for service {svc}")
def validate_all_groups_users_for_service(service):
logger.debug(f"Performing validation for service {service}")
for user in instance.user_set.all():
svc.validate_user(user)
service.validate_user(user)
transaction.on_commit(validate_all_groups_users_for_service)
transaction.on_commit(lambda service=svc: validate_all_groups_users_for_service(service))
got_change = True
break # Found service, break out of services iteration and go back to permission iteration
if not got_change:
logger.debug(f"Permission change for group {instance} was not service permission, ignoring")
logger.debug(f"Permission change for group {instance} was not a service permission, ignoring")
@receiver(m2m_changed, sender=State.permissions.through)
@ -115,12 +116,12 @@ def m2m_changed_state_permissions(sender, instance, action, pk_set, *args, **kwa
if svc.access_perm == path_perm:
logger.debug(f"Permissions changed for state {instance} on service {svc}, re-validating services for state users")
def validate_all_state_users_for_service():
logger.debug(f"Performing validation for service {svc}")
def validate_all_state_users_for_service(service):
logger.debug(f"Performing validation for service {service}")
for profile in instance.userprofile_set.all():
svc.validate_user(profile.user)
service.validate_user(profile.user)
transaction.on_commit(validate_all_state_users_for_service)
transaction.on_commit(lambda service=svc: validate_all_state_users_for_service(service))
got_change = True
break # Found service, break out of services iteration and go back to permission iteration
if not got_change:

View File

@ -28,11 +28,7 @@ x-allianceauth-base: &allianceauth-base
x-allianceauth-health-check: &allianceauth-health-checks
healthcheck:
test: [
"CMD",
"/memory_check.sh",
"500000000"
]
test: ["CMD", "/memory_check.sh", "500000000"]
interval: 60s
timeout: 10s
retries: 3
@ -89,47 +85,25 @@ services:
max-file: "5"
allianceauth_gunicorn:
ports:
- 8000:8000
container_name: allianceauth_gunicorn
<<: [*allianceauth-base]
entrypoint: [
"gunicorn",
"myauth.wsgi",
"--bind=0.0.0.0:8000",
"--workers=3",
"--timeout=120",
"--max-requests=500",
"--max-requests-jitter=50"
]
entrypoint: ["gunicorn", "myauth.wsgi", "--bind=0.0.0.0:8000", "--workers=3", "--timeout=120", "--max-requests=500", "--max-requests-jitter=50"]
ports:
- 8000:8000
allianceauth_beat:
container_name: allianceauth_worker_beat
<<: [*allianceauth-base]
entrypoint: [
"celery",
"-A",
"myauth",
"beat"
]
entrypoint: ["celery", "-A", "myauth", "beat"]
allianceauth_worker:
<<: [*allianceauth-base, *allianceauth-health-checks]
entrypoint: [
"celery",
"-A",
"myauth",
"worker",
"--pool=threads",
"--concurrency=5",
"-n",
"worker_%n"
]
entrypoint: ["celery", "-A", "myauth", "worker", "--pool=threads", "--concurrency=5", "-n", "worker_%n"]
deploy:
replicas: 2
grafana:
image: grafana/grafana-oss:11.2.0
image: grafana/grafana-oss:latest
restart: always
depends_on:
- auth_mysql
@ -156,13 +130,6 @@ services:
- ${PROXY_HTTP_PORT:-80}:80
- ${PROXY_DASH_PORT:-81}:81
- ${PROXY_HTTPS_PORT:-443}:443
# Uncomment this section to use a dedicated database for Nginx Proxy Manager
# environment:
# DB_MYSQL_HOST: "proxy-db"
# DB_MYSQL_PORT: 3306
# DB_MYSQL_USER: "npm"
# DB_MYSQL_PASSWORD: "${PROXY_MYSQL_PASS?err}"
# DB_MYSQL_NAME: "npm"
volumes:
- proxy-data:/data
- proxy-le:/etc/letsencrypt
@ -174,25 +141,6 @@ services:
max-size: "10Mb"
max-file: "5"
# Uncomment this section to use a dedicated database for Nginx Proxy Manager
# proxy-db:
# image: 'jc21/mariadb-aria:latest'
# restart: always
# environment:
# MYSQL_ROOT_PASSWORD: "${PROXY_MYSQL_PASS_ROOT?err}"
# MYSQL_DATABASE: 'npm'
# MYSQL_USER: 'npm'
# MYSQL_PASSWORD: "${PROXY_MYSQL_PASS?err}"
# ports:
# - 3306
# volumes:
# - proxy-db:/var/lib/mysql
# logging:
# driver: "json-file"
# options:
# max-size: "1Mb"
# max-file: "5"
volumes:
redis-data:
static-volume:

View File

@ -1,7 +1,7 @@
[build-system]
build-backend = "flit_core.buildapi"
requires = [
"flit-core<4,>=3.2",
"flit-core>=3.2,<4",
]
[project]
@ -29,6 +29,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
]
@ -39,15 +40,15 @@ dynamic = [
dependencies = [
"bcrypt",
"beautifulsoup4",
"celery<6,>=5.4",
"celery>=5.4,<6",
"celery-once>=3.0.1",
"django<5.2,>=5.1",
"django>=5.1,<5.2",
"django-bootstrap-form",
"django-bootstrap5>=23.3",
"django-celery-beat>=2.7",
"django-esi>=5",
"django-redis>=5.4",
"django-registration<4,>=3.3",
"django-registration>=5.1,<6",
"django-solo",
"django-sortedm2m",
"dnspython",
@ -67,7 +68,7 @@ optional-dependencies.docs = [
"myst-parser>=4",
"sphinx>=8",
"sphinx-copybutton",
"sphinx-rtd-theme<4,>=3.0.0rc1",
"sphinx-rtd-theme>=3,<4",
"sphinx-tabs",
"sphinxcontrib-django",
]