mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-13 10:36:25 +01:00
Compare commits
14 Commits
v4.4.2
...
63fb449060
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63fb449060 | ||
|
|
235675fa9b | ||
|
|
a065f043eb | ||
|
|
0839920032 | ||
|
|
29ad4acff7 | ||
|
|
3a5b84d1f9 | ||
|
|
bbcb94021e | ||
|
|
d50f13528b | ||
|
|
c88521af88 | ||
|
|
2bd5ff8723 | ||
|
|
84484cebcb | ||
|
|
5ee34fcb2d | ||
|
|
046473def1 | ||
|
|
6aaba2bf3d |
@@ -51,30 +51,6 @@ secret_detection:
|
||||
stage: gitlab
|
||||
before_script: []
|
||||
|
||||
test-3.8-core:
|
||||
<<: *only-default
|
||||
image: python:3.8-bookworm
|
||||
script:
|
||||
- tox -e py38-core
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
test-3.9-core:
|
||||
<<: *only-default
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-core
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
test-3.10-core:
|
||||
<<: *only-default
|
||||
image: python:3.10-bookworm
|
||||
@@ -111,29 +87,18 @@ test-3.12-core:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
test-3.8-all:
|
||||
test-3.13-core:
|
||||
<<: *only-default
|
||||
image: python:3.8-bookworm
|
||||
image: python:3.13-rc-bookworm
|
||||
script:
|
||||
- tox -e py38-all
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
test-3.9-all:
|
||||
<<: *only-default
|
||||
image: python:3.9-bookworm
|
||||
script:
|
||||
- tox -e py39-all
|
||||
- tox -e py313-core
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
allow_failure: true
|
||||
|
||||
test-3.10-all:
|
||||
<<: *only-default
|
||||
@@ -172,9 +137,22 @@ test-3.12-all:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
test-3.13-all:
|
||||
<<: *only-default
|
||||
image: python:3.13-rc-bookworm
|
||||
script:
|
||||
- tox -e py313-all
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
allow_failure: true
|
||||
|
||||
build-test:
|
||||
stage: test
|
||||
image: python:3.11-bookworm
|
||||
image: python:3.12-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
@@ -193,13 +171,13 @@ build-test:
|
||||
|
||||
test-docs:
|
||||
<<: *only-default
|
||||
image: python:3.11-bookworm
|
||||
image: python:3.12-bookworm
|
||||
script:
|
||||
- tox -e docs
|
||||
|
||||
deploy_production:
|
||||
stage: deploy
|
||||
image: python:3.11-bookworm
|
||||
image: python:3.12-bookworm
|
||||
|
||||
before_script:
|
||||
- python -m pip install --upgrade pip
|
||||
@@ -215,10 +193,10 @@ deploy_production:
|
||||
|
||||
build-image:
|
||||
before_script: []
|
||||
image: docker:24.0
|
||||
image: docker:27.0
|
||||
stage: docker
|
||||
services:
|
||||
- docker:24.0-dind
|
||||
- docker:27-dind
|
||||
script: |
|
||||
CURRENT_DATE=$(echo $CI_COMMIT_TIMESTAMP | head -c 10 | tr -d -)
|
||||
IMAGE_TAG=$CI_REGISTRY_IMAGE/auth:$CURRENT_DATE-$CI_COMMIT_SHORT_SHA
|
||||
@@ -239,10 +217,10 @@ build-image:
|
||||
|
||||
build-image-dev:
|
||||
before_script: []
|
||||
image: docker:24.0
|
||||
image: docker:27
|
||||
stage: docker
|
||||
services:
|
||||
- docker:24.0-dind
|
||||
- docker:27-dind
|
||||
script: |
|
||||
CURRENT_DATE=$(echo $CI_COMMIT_TIMESTAMP | head -c 10 | tr -d -)
|
||||
IMAGE_TAG=$CI_REGISTRY_IMAGE/auth:$CURRENT_DATE-$CI_COMMIT_BRANCH-$CI_COMMIT_SHORT_SHA
|
||||
@@ -260,10 +238,10 @@ build-image-dev:
|
||||
|
||||
build-image-mr:
|
||||
before_script: []
|
||||
image: docker:24.0
|
||||
image: docker:27
|
||||
stage: docker
|
||||
services:
|
||||
- docker:24.0-dind
|
||||
- docker:27-dind
|
||||
script: |
|
||||
CURRENT_DATE=$(echo $CI_COMMIT_TIMESTAMP | head -c 10 | tr -d -)
|
||||
IMAGE_TAG=$CI_REGISTRY_IMAGE/auth:$CURRENT_DATE-$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME-$CI_COMMIT_SHORT_SHA
|
||||
|
||||
@@ -9,7 +9,7 @@ repos:
|
||||
rev: v3.15.2
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py38-plus]
|
||||
args: [--py310-plus]
|
||||
- repo: https://github.com/adamchainz/django-upgrade
|
||||
rev: 1.17.0
|
||||
hooks:
|
||||
|
||||
@@ -7,11 +7,11 @@ version: 2
|
||||
|
||||
# Set the version of Python and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-24.04
|
||||
apt_packages:
|
||||
- redis
|
||||
tools:
|
||||
python: "3.11"
|
||||
python: "3.12"
|
||||
jobs:
|
||||
post_system_dependencies:
|
||||
- redis-server --daemonize yes
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.conf import settings
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def active_tasks_count() -> Optional[int]:
|
||||
def active_tasks_count() -> int | None:
|
||||
"""Return count of currently active tasks
|
||||
or None if celery workers are not online.
|
||||
"""
|
||||
@@ -20,7 +20,7 @@ def active_tasks_count() -> Optional[int]:
|
||||
return _tasks_count(inspect.active())
|
||||
|
||||
|
||||
def _tasks_count(data: dict) -> Optional[int]:
|
||||
def _tasks_count(data: dict) -> int | None:
|
||||
"""Return count of tasks in data from celery inspect API."""
|
||||
try:
|
||||
tasks = itertools.chain(*data.values())
|
||||
@@ -29,7 +29,7 @@ def _tasks_count(data: dict) -> Optional[int]:
|
||||
return len(list(tasks))
|
||||
|
||||
|
||||
def queued_tasks_count() -> Optional[int]:
|
||||
def queued_tasks_count() -> int | None:
|
||||
"""Return count of queued tasks. Return None if there was an error."""
|
||||
try:
|
||||
with current_app.connection_or_acquire() as conn:
|
||||
|
||||
@@ -2,7 +2,8 @@ from django.urls import include
|
||||
from django.contrib.auth.decorators import user_passes_test
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from functools import wraps
|
||||
from typing import Callable, Iterable, Optional
|
||||
from typing import Optional
|
||||
from collections.abc import Callable, Iterable
|
||||
|
||||
from django.urls import include
|
||||
from django.contrib import messages
|
||||
@@ -17,7 +18,7 @@ def user_has_main_character(user):
|
||||
|
||||
|
||||
def decorate_url_patterns(
|
||||
urls, decorator: Callable, excluded_views: Optional[Iterable] = None
|
||||
urls, decorator: Callable, excluded_views: Iterable | None = None
|
||||
):
|
||||
"""Decorate views given in url patterns except when they are explicitly excluded.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class _TaskCounts(NamedTuple):
|
||||
retried: int
|
||||
failed: int
|
||||
total: int
|
||||
earliest_task: Optional[dt.datetime]
|
||||
earliest_task: dt.datetime | None
|
||||
hours: int
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class EventSeries:
|
||||
|
||||
_ROOT_KEY = "ALLIANCEAUTH_EVENT_SERIES"
|
||||
|
||||
def __init__(self, key_id: str, redis: Optional[Redis] = None) -> None:
|
||||
def __init__(self, key_id: str, redis: Redis | None = None) -> None:
|
||||
self._redis = get_redis_client_or_stub() if not redis else redis
|
||||
self._key_id = str(key_id)
|
||||
self.clear()
|
||||
@@ -46,7 +46,7 @@ class EventSeries:
|
||||
my_id = self._redis.incr(self._key_counter)
|
||||
self._redis.zadd(self._key_sorted_set, {my_id: event_time.timestamp()})
|
||||
|
||||
def all(self) -> List[dt.datetime]:
|
||||
def all(self) -> list[dt.datetime]:
|
||||
"""List of all known events."""
|
||||
return [
|
||||
event[1]
|
||||
@@ -75,7 +75,7 @@ class EventSeries:
|
||||
maximum = "+inf" if not latest else latest.timestamp()
|
||||
return self._redis.zcount(self._key_sorted_set, min=minimum, max=maximum)
|
||||
|
||||
def first_event(self, earliest: dt.datetime = None) -> Optional[dt.datetime]:
|
||||
def first_event(self, earliest: dt.datetime = None) -> dt.datetime | None:
|
||||
"""Date/Time of first event. Returns `None` if series has no events.
|
||||
|
||||
Args:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from typing import List
|
||||
from django import db
|
||||
from django.core.checks import CheckMessage, Error, register, Warning
|
||||
from allianceauth.utils.cache import get_redis_client
|
||||
@@ -7,7 +6,7 @@ from packaging.version import InvalidVersion, Version as Pep440Version
|
||||
from celery import current_app
|
||||
from django.conf import settings
|
||||
from sqlite3.dbapi2 import sqlite_version_info
|
||||
|
||||
import datetime
|
||||
"""
|
||||
A = System Packages
|
||||
B = Configuration
|
||||
@@ -15,8 +14,8 @@ B = Configuration
|
||||
|
||||
|
||||
@register()
|
||||
def django_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def django_settings(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
if hasattr(settings, "SITE_URL"):
|
||||
if settings.SITE_URL[-1] == "/":
|
||||
errors.append(Warning("'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth.", hint="", id="allianceauth.checks.B005"))
|
||||
@@ -33,15 +32,15 @@ def django_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def system_package_redis(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
try:
|
||||
redis_version = Pep440Version(get_redis_client().info()['redis_version'])
|
||||
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=timezone.utc):
|
||||
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):
|
||||
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 == 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"))
|
||||
@@ -54,8 +53,8 @@ def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def system_package_mysql(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
@@ -66,7 +65,7 @@ def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
return errors
|
||||
|
||||
# MySQL 8
|
||||
if mysql_version.major == 8 and mysql_version.minor == 4 and timezone.now() > timezone.datetime(year=2032, month=4, day=30, tzinfo=timezone.utc):
|
||||
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"))
|
||||
@@ -74,7 +73,7 @@ def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
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:
|
||||
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=timezone.utc):
|
||||
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"))
|
||||
elif mysql_version.major < 8: # This will also catch Mariadb 5.x
|
||||
errors.append(Error(f"MySQL or MariaDB {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A009"))
|
||||
@@ -82,8 +81,8 @@ def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def system_package_mariadb(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql": # Still to find a way to determine MySQL vs MariaDB
|
||||
@@ -94,25 +93,25 @@ def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
return errors
|
||||
|
||||
# MariaDB 11
|
||||
if mariadb_version.major == 11 and mariadb_version.minor == 4 and timezone.now() > timezone.datetime(year=2029, month=5, day=19, tzinfo=timezone.utc):
|
||||
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=timezone.utc):
|
||||
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"))
|
||||
if timezone.now() > timezone.datetime(year=2024, month=8, day=21, tzinfo=timezone.utc):
|
||||
if timezone.now() > timezone.datetime(year=2024, month=8, 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.A012"))
|
||||
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 3]: # 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
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 11 and timezone.now() > timezone.datetime(year=2028, month=2, day=10, tzinfo=timezone.utc):
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 11 and timezone.now() > timezone.datetime(year=2028, month=2, day=10, tzinfo=datetime.timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A014"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 6 and timezone.now() > timezone.datetime(year=2026, month=7, day=6, tzinfo=timezone.utc):
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 6 and timezone.now() > timezone.datetime(year=2026, month=7, day=6, tzinfo=datetime.timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A0015"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 5 and timezone.now() > timezone.datetime(year=2025, month=6, day=24, tzinfo=timezone.utc):
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor == 5 and timezone.now() > timezone.datetime(year=2025, month=6, day=24, tzinfo=datetime.timezone.utc):
|
||||
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A016"))
|
||||
elif mariadb_version.major == 10 and mariadb_version.minor in [0, 1, 2, 3, 4, 7, 9, 10]: # 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.A017"))
|
||||
@@ -121,8 +120,8 @@ def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def system_package_sqlite(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "sqlite":
|
||||
try:
|
||||
@@ -136,8 +135,8 @@ def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def sql_settings(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
for connection in db.connections.all():
|
||||
if connection.vendor == "mysql":
|
||||
try:
|
||||
@@ -159,8 +158,8 @@ def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
|
||||
|
||||
@register()
|
||||
def celery_settings(app_configs, **kwargs) -> List[CheckMessage]:
|
||||
errors: List[CheckMessage] = []
|
||||
def celery_settings(app_configs, **kwargs) -> list[CheckMessage]:
|
||||
errors: list[CheckMessage] = []
|
||||
|
||||
try:
|
||||
if current_app.conf.broker_transport_options != {'priority_steps': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'queue_order_strategy': 'priority'}:
|
||||
|
||||
@@ -235,7 +235,7 @@ class EveCharacter(models.Model):
|
||||
return self.corporation_id == DOOMHEIM_CORPORATION_ID
|
||||
|
||||
@property
|
||||
def alliance(self) -> Union[EveAllianceInfo, None]:
|
||||
def alliance(self) -> EveAllianceInfo | None:
|
||||
"""
|
||||
Pseudo foreign key from alliance_id to EveAllianceInfo
|
||||
:raises: EveAllianceInfo.DoesNotExist
|
||||
@@ -255,7 +255,7 @@ class EveCharacter(models.Model):
|
||||
return EveCorporationInfo.objects.get(corporation_id=self.corporation_id)
|
||||
|
||||
@property
|
||||
def faction(self) -> Union[EveFactionInfo, None]:
|
||||
def faction(self) -> EveFactionInfo | None:
|
||||
"""
|
||||
Pseudo foreign key from faction_id to EveFactionInfo
|
||||
:raises: EveFactionInfo.DoesNotExist
|
||||
|
||||
@@ -13,7 +13,7 @@ from allianceauth.framework.api.user import get_sentinel_user
|
||||
|
||||
def get_main_character_from_evecharacter(
|
||||
character: EveCharacter,
|
||||
) -> Optional[EveCharacter]:
|
||||
) -> EveCharacter | None:
|
||||
"""
|
||||
Get the main character for a given EveCharacter or None when no main character is set
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ def get_all_characters_from_user(user: User) -> list:
|
||||
return characters
|
||||
|
||||
|
||||
def get_main_character_from_user(user: User) -> Optional[EveCharacter]:
|
||||
def get_main_character_from_user(user: User) -> EveCharacter | None:
|
||||
"""
|
||||
Get the main character from a user
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ class AuthGroup(models.Model):
|
||||
def __str__(self):
|
||||
return self.group.name
|
||||
|
||||
def group_request_approvers(self) -> Set[User]:
|
||||
def group_request_approvers(self) -> set[User]:
|
||||
"""Return all users who can approve a group request."""
|
||||
return set(
|
||||
self.group_leaders.all()
|
||||
|
||||
@@ -5,7 +5,7 @@ from typing import Optional
|
||||
|
||||
class ApplicationManager(models.Manager):
|
||||
|
||||
def pending_requests_count_for_user(self, user: User) -> Optional[int]:
|
||||
def pending_requests_count_for_user(self, user: User) -> int | None:
|
||||
"""Returns the number of pending group requests for the given user"""
|
||||
if user.is_superuser:
|
||||
return self.filter(approved__isnull=True).count()
|
||||
|
||||
@@ -35,12 +35,12 @@ class MenuItemAdmin(admin.ModelAdmin):
|
||||
]
|
||||
ordering = ["parent", "order", "text"]
|
||||
|
||||
def get_form(self, request: HttpRequest, obj: Optional[MenuItem] = None, **kwargs):
|
||||
def get_form(self, request: HttpRequest, obj: MenuItem | None = None, **kwargs):
|
||||
kwargs["form"] = self._choose_form(request, obj)
|
||||
return super().get_form(request, obj, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _choose_form(cls, request: HttpRequest, obj: Optional[MenuItem]):
|
||||
def _choose_form(cls, request: HttpRequest, obj: MenuItem | None):
|
||||
"""Return the form for the current menu item type."""
|
||||
if obj: # change
|
||||
if obj.hook_hash:
|
||||
@@ -104,7 +104,7 @@ class MenuItemAdmin(admin.ModelAdmin):
|
||||
@staticmethod
|
||||
def _type_from_request(
|
||||
request: HttpRequest, default=None
|
||||
) -> Optional[MenuItemType]:
|
||||
) -> MenuItemType | None:
|
||||
try:
|
||||
return MenuItemType(request.GET.get("type"))
|
||||
except ValueError:
|
||||
|
||||
@@ -14,8 +14,8 @@ class MenuItemHookCustom(MenuItemHook):
|
||||
text: str,
|
||||
classes: str,
|
||||
url_name: str,
|
||||
order: Optional[int] = None,
|
||||
navactive: Optional[List[str]] = None,
|
||||
order: int | None = None,
|
||||
navactive: list[str] | None = None,
|
||||
):
|
||||
super().__init__(text, classes, url_name, order, navactive)
|
||||
self.url = ""
|
||||
|
||||
@@ -33,8 +33,8 @@ class MenuItemHook:
|
||||
text: str,
|
||||
classes: str,
|
||||
url_name: str,
|
||||
order: Optional[int] = None,
|
||||
navactive: Optional[List[str]] = None,
|
||||
order: int | None = None,
|
||||
navactive: list[str] | None = None,
|
||||
):
|
||||
self.text = text
|
||||
self.classes = classes
|
||||
|
||||
@@ -56,8 +56,8 @@ class RenderedMenuItem:
|
||||
|
||||
menu_item: MenuItem
|
||||
|
||||
children: List["RenderedMenuItem"] = field(default_factory=list)
|
||||
count: Optional[int] = None
|
||||
children: list["RenderedMenuItem"] = field(default_factory=list)
|
||||
count: int | None = None
|
||||
html: str = ""
|
||||
html_id: str = ""
|
||||
|
||||
@@ -78,7 +78,7 @@ class RenderedMenuItem:
|
||||
self.html_id = hook_obj.html_id
|
||||
|
||||
|
||||
def render_menu(request: HttpRequest) -> List[RenderedMenuItem]:
|
||||
def render_menu(request: HttpRequest) -> list[RenderedMenuItem]:
|
||||
"""Return the rendered side menu for including in a template.
|
||||
|
||||
This function is creating BS5 style menus.
|
||||
@@ -88,7 +88,7 @@ def render_menu(request: HttpRequest) -> List[RenderedMenuItem]:
|
||||
# Menu items needs to be rendered with the new BS5 template
|
||||
bs5_template = "menu/menu-item-bs5.html"
|
||||
|
||||
rendered_items: Dict[int, RenderedMenuItem] = {}
|
||||
rendered_items: dict[int, RenderedMenuItem] = {}
|
||||
menu_items: QuerySet[MenuItem] = MenuItem.objects.order_by(
|
||||
"parent", "order", "text"
|
||||
)
|
||||
@@ -131,7 +131,7 @@ def render_menu(request: HttpRequest) -> List[RenderedMenuItem]:
|
||||
return list(rendered_items.values())
|
||||
|
||||
|
||||
def _gather_menu_items_from_hooks() -> Dict[str, MenuItemHook]:
|
||||
def _gather_menu_items_from_hooks() -> dict[str, MenuItemHook]:
|
||||
hook_items = {}
|
||||
for hook in get_hooks("menu_item_hook"):
|
||||
f = hook()
|
||||
@@ -161,14 +161,14 @@ def _render_link_item(
|
||||
|
||||
|
||||
def _render_folder_items(
|
||||
request: HttpRequest, rendered_items: Dict[int, RenderedMenuItem], new_template: str
|
||||
request: HttpRequest, rendered_items: dict[int, RenderedMenuItem], new_template: str
|
||||
):
|
||||
for item in rendered_items.values():
|
||||
if item.menu_item.is_folder:
|
||||
item.update_html(request=request, template=new_template)
|
||||
|
||||
|
||||
def _remove_empty_folders(rendered_items: Dict[int, RenderedMenuItem]):
|
||||
def _remove_empty_folders(rendered_items: dict[int, RenderedMenuItem]):
|
||||
ids_to_remove = []
|
||||
for item_id, item in rendered_items.items():
|
||||
if item.is_folder and not item.children:
|
||||
|
||||
@@ -347,9 +347,9 @@ class TestRenderedMenuItem(TestCase):
|
||||
|
||||
|
||||
class _ParsedMenuItem(NamedTuple):
|
||||
classes: List[str]
|
||||
classes: list[str]
|
||||
text: str
|
||||
count: Optional[int]
|
||||
count: int | None
|
||||
|
||||
|
||||
def parse_html(obj: RenderedMenuItem) -> _ParsedMenuItem:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from string import Formatter
|
||||
from django.urls import include, re_path
|
||||
from typing import Iterable, Optional
|
||||
from typing import Optional
|
||||
from collections.abc import Iterable
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
@@ -175,7 +176,7 @@ class UrlHook:
|
||||
urls,
|
||||
namespace: str,
|
||||
base_url: str,
|
||||
excluded_views : Optional[Iterable[str]] = None
|
||||
excluded_views : Iterable[str] | None = None
|
||||
):
|
||||
self.include_pattern = re_path(base_url, include(urls, namespace=namespace))
|
||||
self.excluded_views = set(excluded_views or [])
|
||||
|
||||
@@ -28,7 +28,7 @@ from .models import DiscordUser # noqa
|
||||
__all__ = ["create_bot_client", "group_to_role", "server_name", "DiscordUser", "Role"]
|
||||
|
||||
|
||||
def discord_guild_id() -> Optional[int]:
|
||||
def discord_guild_id() -> int | None:
|
||||
"""Guild ID of configured Discord server.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -36,7 +36,7 @@ def calculate_roles_for_user(
|
||||
client: DiscordClient,
|
||||
discord_uid: int,
|
||||
state_name: str = None,
|
||||
) -> Tuple[RolesSet, Optional[bool]]:
|
||||
) -> tuple[RolesSet, bool | None]:
|
||||
"""Calculate current Discord roles for an Auth user.
|
||||
|
||||
Takes into account reserved groups and existing managed roles (e.g. nitro).
|
||||
@@ -68,7 +68,7 @@ def calculate_roles_for_user(
|
||||
return roles_calculated.union(roles_persistent), True
|
||||
|
||||
|
||||
def _user_group_names(user: User, state_name: str = None) -> List[str]:
|
||||
def _user_group_names(user: User, state_name: str = None) -> list[str]:
|
||||
"""Names of groups and state the given user is a member of."""
|
||||
if not state_name:
|
||||
state_name = user.profile.state.name
|
||||
@@ -77,7 +77,7 @@ def _user_group_names(user: User, state_name: str = None) -> List[str]:
|
||||
return group_names
|
||||
|
||||
|
||||
def user_formatted_nick(user: User) -> Optional[str]:
|
||||
def user_formatted_nick(user: User) -> str | None:
|
||||
"""Name of the given user's main character with name formatting applied.
|
||||
|
||||
Returns:
|
||||
@@ -90,7 +90,7 @@ def user_formatted_nick(user: User) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def group_to_role(group: Group) -> Optional[Role]:
|
||||
def group_to_role(group: Group) -> Role | None:
|
||||
"""Fetch the Discord role matching the given Django group by name.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -6,7 +6,8 @@ from enum import IntEnum
|
||||
from hashlib import md5
|
||||
from http import HTTPStatus
|
||||
from time import sleep
|
||||
from typing import Iterable, List, Optional, Set, Tuple
|
||||
from typing import List, Optional, Set, Tuple
|
||||
from collections.abc import Iterable
|
||||
from urllib.parse import urljoin
|
||||
from uuid import uuid1
|
||||
|
||||
@@ -233,7 +234,7 @@ class DiscordClient:
|
||||
|
||||
# guild roles
|
||||
|
||||
def guild_roles(self, guild_id: int, use_cache: bool = True) -> Set[Role]:
|
||||
def guild_roles(self, guild_id: int, use_cache: bool = True) -> set[Role]:
|
||||
"""Fetch all roles for this guild.
|
||||
|
||||
Args:
|
||||
@@ -268,7 +269,7 @@ class DiscordClient:
|
||||
|
||||
def create_guild_role(
|
||||
self, guild_id: int, role_name: str, **kwargs
|
||||
) -> Optional[Role]:
|
||||
) -> Role | None:
|
||||
"""Create a new guild role with the given name.
|
||||
|
||||
See official documentation for additional optional parameters.
|
||||
@@ -318,7 +319,7 @@ class DiscordClient:
|
||||
gen_key = cls._generate_hash(f'{guild_id}')
|
||||
return f'{cls._KEYPREFIX_GUILD_ROLES}__{gen_key}'
|
||||
|
||||
def match_role_from_name(self, guild_id: int, role_name: str) -> Optional[Role]:
|
||||
def match_role_from_name(self, guild_id: int, role_name: str) -> Role | None:
|
||||
"""Fetch Discord role matching the given name (cached).
|
||||
|
||||
Args:
|
||||
@@ -333,7 +334,7 @@ class DiscordClient:
|
||||
|
||||
def match_or_create_roles_from_names(
|
||||
self, guild_id: int, role_names: Iterable[str]
|
||||
) -> List[Tuple[Role, bool]]:
|
||||
) -> list[tuple[Role, bool]]:
|
||||
"""Fetch or create Discord roles matching the given names (cached).
|
||||
|
||||
Will try to match with existing roles names
|
||||
@@ -361,7 +362,7 @@ class DiscordClient:
|
||||
|
||||
def match_or_create_role_from_name(
|
||||
self, guild_id: int, role_name: str, guild_roles: RolesSet = None
|
||||
) -> Tuple[Role, bool]:
|
||||
) -> tuple[Role, bool]:
|
||||
"""Fetch or create Discord role matching the given name.
|
||||
|
||||
Will try to match with existing roles names
|
||||
@@ -418,7 +419,7 @@ class DiscordClient:
|
||||
access_token: str,
|
||||
role_ids: list = None,
|
||||
nick: str = None
|
||||
) -> Optional[bool]:
|
||||
) -> bool | None:
|
||||
"""Adds a user to the guild.
|
||||
|
||||
Returns:
|
||||
@@ -442,7 +443,7 @@ class DiscordClient:
|
||||
return None
|
||||
return False
|
||||
|
||||
def guild_member(self, guild_id: int, user_id: int) -> Optional[GuildMember]:
|
||||
def guild_member(self, guild_id: int, user_id: int) -> GuildMember | None:
|
||||
"""Fetch info for a guild member.
|
||||
|
||||
Args:
|
||||
@@ -461,8 +462,8 @@ class DiscordClient:
|
||||
return GuildMember.from_dict(r.json())
|
||||
|
||||
def modify_guild_member(
|
||||
self, guild_id: int, user_id: int, role_ids: List[int] = None, nick: str = None
|
||||
) -> Optional[bool]:
|
||||
self, guild_id: int, user_id: int, role_ids: list[int] = None, nick: str = None
|
||||
) -> bool | None:
|
||||
"""Set properties of a guild member.
|
||||
|
||||
Args:
|
||||
@@ -501,7 +502,7 @@ class DiscordClient:
|
||||
return True
|
||||
return False
|
||||
|
||||
def remove_guild_member(self, guild_id: int, user_id: int) -> Optional[bool]:
|
||||
def remove_guild_member(self, guild_id: int, user_id: int) -> bool | None:
|
||||
"""Remove a member from a guild.
|
||||
|
||||
Args:
|
||||
@@ -529,7 +530,7 @@ class DiscordClient:
|
||||
|
||||
def add_guild_member_role(
|
||||
self, guild_id: int, user_id: int, role_id: int
|
||||
) -> Optional[bool]:
|
||||
) -> bool | None:
|
||||
"""Adds a role to a guild member
|
||||
|
||||
Returns:
|
||||
@@ -549,7 +550,7 @@ class DiscordClient:
|
||||
|
||||
def remove_guild_member_role(
|
||||
self, guild_id: int, user_id: int, role_id: int
|
||||
) -> Optional[bool]:
|
||||
) -> bool | None:
|
||||
"""Remove a role to a guild member
|
||||
|
||||
Args:
|
||||
@@ -572,7 +573,7 @@ class DiscordClient:
|
||||
return True
|
||||
return False
|
||||
|
||||
def guild_member_roles(self, guild_id: int, user_id: int) -> Optional[RolesSet]:
|
||||
def guild_member_roles(self, guild_id: int, user_id: int) -> RolesSet | None:
|
||||
"""Fetch the current guild roles of a guild member.
|
||||
|
||||
Args:
|
||||
@@ -821,6 +822,6 @@ class DiscordClient:
|
||||
return md5(key.encode('utf-8')).hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def _sanitize_role_ids(role_ids: Iterable[int]) -> List[int]:
|
||||
def _sanitize_role_ids(role_ids: Iterable[int]) -> list[int]:
|
||||
"""Sanitize a list of role IDs, i.e. make sure its a list of unique integers."""
|
||||
return [int(role_id) for role_id in set(role_ids)]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from copy import copy
|
||||
from typing import Iterable, List, Optional, Set, Tuple
|
||||
from typing import List, Optional, Set, Tuple
|
||||
from collections.abc import Iterable
|
||||
|
||||
from .models import Role
|
||||
|
||||
@@ -50,7 +51,7 @@ class RolesSet:
|
||||
def __len__(self):
|
||||
return len(self._roles.keys())
|
||||
|
||||
def has_roles(self, role_ids: Set[int]) -> bool:
|
||||
def has_roles(self, role_ids: set[int]) -> bool:
|
||||
"""True if this objects contains all roles defined by given role_ids
|
||||
incl. managed roles.
|
||||
"""
|
||||
@@ -58,7 +59,7 @@ class RolesSet:
|
||||
all_role_ids = self._roles.keys()
|
||||
return role_ids.issubset(all_role_ids)
|
||||
|
||||
def ids(self) -> Set[int]:
|
||||
def ids(self) -> set[int]:
|
||||
"""Set of all role IDs."""
|
||||
return set(self._roles.keys())
|
||||
|
||||
@@ -114,7 +115,7 @@ class RolesSet:
|
||||
new_ids = self.ids().difference(other.ids())
|
||||
return self.subset(role_ids=new_ids)
|
||||
|
||||
def role_by_name(self, role_name: str) -> Optional[Role]:
|
||||
def role_by_name(self, role_name: str) -> Role | None:
|
||||
"""Role if one with matching name is found else None."""
|
||||
role_name = Role.sanitize_name(role_name)
|
||||
if role_name in self._roles_by_name:
|
||||
@@ -123,7 +124,7 @@ class RolesSet:
|
||||
|
||||
@classmethod
|
||||
def create_from_matched_roles(
|
||||
cls, matched_roles: List[Tuple[Role, bool]]
|
||||
cls, matched_roles: list[tuple[Role, bool]]
|
||||
) -> "RolesSet":
|
||||
"""Create new instance from the given list of matches roles.
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class Guild:
|
||||
|
||||
id: int
|
||||
name: str
|
||||
roles: FrozenSet[Role]
|
||||
roles: frozenset[Role]
|
||||
|
||||
def __post_init__(self):
|
||||
object.__setattr__(self, "id", int(self.id))
|
||||
@@ -95,7 +95,7 @@ class GuildMember:
|
||||
|
||||
_NICK_MAX_CHARS = 32
|
||||
|
||||
roles: FrozenSet[int]
|
||||
roles: frozenset[int]
|
||||
nick: str = None
|
||||
user: User = None
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ class DiscordUser(models.Model):
|
||||
logger.warning('Failed to update nickname for %s', self.user)
|
||||
return success
|
||||
|
||||
def update_groups(self, state_name: str = None) -> Optional[bool]:
|
||||
def update_groups(self, state_name: str = None) -> bool | None:
|
||||
"""update groups for a user based on his current group memberships.
|
||||
Will add or remove roles of a user as needed.
|
||||
|
||||
@@ -134,7 +134,7 @@ class DiscordUser(models.Model):
|
||||
logger.info('No need to update roles for user %s', self.user)
|
||||
return True
|
||||
|
||||
def update_username(self) -> Optional[bool]:
|
||||
def update_username(self) -> bool | None:
|
||||
"""Updates the username incl. the discriminator
|
||||
from the Discord server and saves it
|
||||
|
||||
@@ -159,7 +159,7 @@ class DiscordUser(models.Model):
|
||||
notify_user: bool = False,
|
||||
is_rate_limited: bool = True,
|
||||
handle_api_exceptions: bool = False
|
||||
) -> Optional[bool]:
|
||||
) -> bool | None:
|
||||
"""Deletes the Discount user both on the server and locally
|
||||
|
||||
Params:
|
||||
|
||||
@@ -438,7 +438,7 @@ class TestUserHasAccount(NoSocketsTestCase):
|
||||
self.assertFalse(DiscordUser.objects.user_has_account(self.user))
|
||||
|
||||
def test_return_false_if_user_does_not_exist(self):
|
||||
my_user = User(username='Dummy')
|
||||
my_user = AuthUtils.create_user("test_return_false_if_user_does_not_exist")
|
||||
self.assertFalse(DiscordUser.objects.user_has_account(my_user))
|
||||
|
||||
def test_return_false_if_not_called_with_user_object(self):
|
||||
|
||||
@@ -181,7 +181,7 @@ class SmfManager:
|
||||
return out
|
||||
|
||||
@classmethod
|
||||
def add_user(cls, username, email_address, groups, main_character: EveCharacter) -> Tuple:
|
||||
def add_user(cls, username, email_address, groups, main_character: EveCharacter) -> tuple:
|
||||
"""
|
||||
Add a user to SMF
|
||||
:param username:
|
||||
|
||||
@@ -262,7 +262,7 @@ class AuthUtils:
|
||||
|
||||
@classmethod
|
||||
def add_permissions_to_user_by_name(
|
||||
cls, perms: List[str], user: User, disconnect_signals: bool = True
|
||||
cls, perms: list[str], user: User, disconnect_signals: bool = True
|
||||
) -> User:
|
||||
"""Add permissions given by name to a user
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ class ThemeHook:
|
||||
def __init__(self,
|
||||
name: str,
|
||||
description: str,
|
||||
css: List[dict],
|
||||
js: List[dict],
|
||||
css_template: Optional[str] = None,
|
||||
js_template: Optional[str] = None,
|
||||
html_tags: Optional[str] = "",
|
||||
header_padding: Optional[str] = "4em"):
|
||||
css: list[dict],
|
||||
js: list[dict],
|
||||
css_template: str | None = None,
|
||||
js_template: str | None = None,
|
||||
html_tags: str | None = "",
|
||||
header_padding: str | None = "4em"):
|
||||
"""
|
||||
:param name: Theme python name
|
||||
:type name: str
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from typing import List, Iterable, Callable
|
||||
from typing import List
|
||||
from collections.abc import Iterable, Callable
|
||||
|
||||
from django.urls import include
|
||||
import esi.urls
|
||||
@@ -24,8 +25,8 @@ admin.site.site_header = NAME
|
||||
|
||||
|
||||
def urls_from_apps(
|
||||
apps_hook_functions: Iterable[Callable], public_views_allowed: List[str]
|
||||
) -> List[URLPattern]:
|
||||
apps_hook_functions: Iterable[Callable], public_views_allowed: list[str]
|
||||
) -> list[URLPattern]:
|
||||
"""Return urls from apps and add default decorators."""
|
||||
|
||||
url_patterns = []
|
||||
|
||||
@@ -22,7 +22,7 @@ class ItemCounter:
|
||||
DEFAULT_CACHE_TIMEOUT = 24 * 3600
|
||||
|
||||
def __init__(
|
||||
self, name: str, minimum: Optional[int] = None, redis: Optional[Redis] = None
|
||||
self, name: str, minimum: int | None = None, redis: Redis | None = None
|
||||
) -> None:
|
||||
if not name:
|
||||
raise ValueError("Must define a name")
|
||||
@@ -60,6 +60,6 @@ class ItemCounter:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def value(self) -> Optional[int]:
|
||||
def value(self) -> int | None:
|
||||
"""Return current value or None if not yet initialized."""
|
||||
return cache.get(self._cache_key)
|
||||
|
||||
@@ -18,7 +18,7 @@ MUMBLE_URL = "mumble.example.com"
|
||||
|
||||
Add the following lines to your `.env` file
|
||||
|
||||
```env
|
||||
```bash
|
||||
# Mumble
|
||||
MUMBLE_SUPERUSER_PASSWORD = superuser_password
|
||||
MUMBLE_ICESECRETWRITE = icesecretwrite
|
||||
|
||||
@@ -25,7 +25,7 @@ BROADCAST_SERVICE_NAME = "broadcast"
|
||||
|
||||
Add the following lines to your `.env` file
|
||||
|
||||
```env
|
||||
```bash
|
||||
# Openfire
|
||||
OPENFIRE_SECRET_KEY = superuser_password
|
||||
BROADCAST_USER_PASSWORD = icesecretwrite
|
||||
|
||||
@@ -34,7 +34,7 @@ CELERYBEAT_SCHEDULE['run_ts3_group_update'] = {
|
||||
|
||||
Add the following lines to your `.env` file
|
||||
|
||||
```env
|
||||
```bash
|
||||
# Temspeak
|
||||
TEAMSPEAK3_SERVERQUERY_USER = "serverquery"
|
||||
TEAMSPEAK3_SERVERQUERY_PASSWORD = ""
|
||||
|
||||
@@ -29,7 +29,7 @@ Replace your docker-compose.yml with the contents of <https://gitlab.com/allianc
|
||||
|
||||
V3.x installs likely used a dedicated database for Nginx Proxy Manager, you can either setup NPM again without a database, or uncomment the sections noted to maintain this configuration
|
||||
|
||||
```docker-compose
|
||||
```docker
|
||||
proxy:
|
||||
...
|
||||
# Uncomment this section to use a dedicated database for Nginx Proxy Manager
|
||||
@@ -64,7 +64,7 @@ V3.x installs likely used a dedicated database for Nginx Proxy Manager, you can
|
||||
|
||||
You will need to add some entries to your .env file
|
||||
|
||||
```env
|
||||
```bash
|
||||
AA_DB_CHARSET=utf8mb4
|
||||
GF_SECURITY_ADMIN_USERNAME=admin
|
||||
```
|
||||
|
||||
@@ -122,7 +122,7 @@ a2dissite 000-default.conf
|
||||
|
||||
## Sample Config File
|
||||
|
||||
```ini
|
||||
```apacheconf
|
||||
<VirtualHost *:80>
|
||||
ServerName auth.example.com
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Tuning usually has benefits and costs and should only be performed by experience
|
||||
:::{toctree}
|
||||
:maxdepth: 1
|
||||
|
||||
gunicorn
|
||||
web
|
||||
celery
|
||||
redis
|
||||
python
|
||||
|
||||
@@ -99,7 +99,7 @@ Replace the nginx service in your docker-compose as follows
|
||||
|
||||
Modify your nginx.conf as follows
|
||||
|
||||
```conf
|
||||
```nginx
|
||||
load_module modules/ngx_http_brotli_static_module.so;
|
||||
load_module modules/ngx_http_brotli_filter_module.so;
|
||||
...
|
||||
|
||||
@@ -15,7 +15,7 @@ license = { file = "LICENSE" }
|
||||
authors = [
|
||||
{ name = "Alliance Auth", email = "adarnof@gmail.com" },
|
||||
]
|
||||
requires-python = ">=3.8"
|
||||
requires-python = ">=3.10"
|
||||
classifiers = [
|
||||
"Environment :: Web Environment",
|
||||
"Framework :: Celery",
|
||||
@@ -26,8 +26,6 @@ classifiers = [
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
@@ -43,10 +41,10 @@ dependencies = [
|
||||
"beautifulsoup4",
|
||||
"celery<6,>=5.2",
|
||||
"celery-once>=3.0.1",
|
||||
"django<5,>=4.2",
|
||||
"django<5.2,>=5.1",
|
||||
"django-bootstrap-form",
|
||||
"django-bootstrap5>=23.3",
|
||||
"django-celery-beat>=2.3",
|
||||
"django-celery-beat>=2.7",
|
||||
"django-esi>=5",
|
||||
"django-redis>=5.2",
|
||||
"django-registration<3.4,>=3.3",
|
||||
|
||||
7
tox.ini
7
tox.ini
@@ -2,18 +2,17 @@
|
||||
isolated_build = true
|
||||
skipsdist = true
|
||||
usedevelop = true
|
||||
envlist = py{38,39,310,311,312}-{all,core}, docs
|
||||
envlist = py{310,311,312,313}-{all,core}, docs
|
||||
|
||||
[testenv]
|
||||
setenv =
|
||||
all: DJANGO_SETTINGS_MODULE = tests.settings_all
|
||||
core: DJANGO_SETTINGS_MODULE = tests.settings_core
|
||||
basepython =
|
||||
py38: python3.8
|
||||
py39: python3.9
|
||||
py310: python3.10
|
||||
py311: python3.11
|
||||
py312: python3.12
|
||||
py313: python3.13
|
||||
deps=
|
||||
coverage
|
||||
install_command = pip install -e ".[test]" -U {opts} {packages}
|
||||
@@ -25,7 +24,7 @@ commands =
|
||||
|
||||
[testenv:docs]
|
||||
description = invoke sphinx-build to build the HTML docs
|
||||
basepython = python3.11
|
||||
basepython = python3.12
|
||||
install_command = pip install -e ".[docs]" -U {opts} {packages}
|
||||
commands =
|
||||
sphinx-build -T -E -b html -d "{toxworkdir}/docs_doctree" -D language=en docs "{toxworkdir}/docs_out" {posargs}
|
||||
|
||||
Reference in New Issue
Block a user