Merge branch 'v4-bumps' into 'v4.x'

V4.x Major versions

See merge request allianceauth/allianceauth!1502
This commit is contained in:
Ariel Rin 2023-06-09 06:07:39 +00:00
commit 4aff4006e3
32 changed files with 88 additions and 56 deletions

View File

@ -25,7 +25,7 @@ before_script:
pre-commit-check: pre-commit-check:
<<: *only-default <<: *only-default
stage: pre-commit stage: pre-commit
image: python:3.8-bullseye image: python:3.11-bullseye
variables: variables:
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
cache: cache:
@ -112,6 +112,19 @@ test-pvpy-core:
path: coverage.xml path: coverage.xml
allow_failure: true allow_failure: true
test-3.12-core:
<<: *only-default
image: python:3.12-rc-bullseye
script:
- tox -e py312-core
artifacts:
when: always
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
test-3.8-all: test-3.8-all:
<<: *only-default <<: *only-default
image: python:3.8-bullseye image: python:3.8-bullseye
@ -174,9 +187,22 @@ test-pvpy-all:
path: coverage.xml path: coverage.xml
allow_failure: true allow_failure: true
test-3.12-all:
<<: *only-default
image: python:3.12-rc-bullseye
script:
- tox -e py312-all
artifacts:
when: always
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
allow_failure: true
build-test: build-test:
stage: test stage: test
image: python:3.10-bullseye image: python:3.11-bullseye
before_script: before_script:
- python -m pip install --upgrade pip - python -m pip install --upgrade pip
@ -195,13 +221,13 @@ build-test:
test-docs: test-docs:
<<: *only-default <<: *only-default
image: python:3.10-bullseye image: python:3.11-bullseye
script: script:
- tox -e docs - tox -e docs
deploy_production: deploy_production:
stage: deploy stage: deploy
image: python:3.10-bullseye image: python:3.11-bullseye
before_script: before_script:
- python -m pip install --upgrade pip - python -m pip install --upgrade pip

View File

@ -49,13 +49,19 @@ repos:
) )
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v3.3.1 rev: v3.4.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [ --py38-plus ] args: [ --py38-plus ]
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.13.0
hooks:
- id: django-upgrade
args: [--target-version=4.2]
- repo: https://github.com/asottile/setup-cfg-fmt - repo: https://github.com/asottile/setup-cfg-fmt
rev: v2.2.0 rev: v2.3.0
hooks: hooks:
- id: setup-cfg-fmt - id: setup-cfg-fmt
args: [ --include-version-classifiers ] args: [ --include-version-classifiers ]

View File

@ -288,7 +288,7 @@ class UserAdmin(BaseUserAdmin):
Behavior of groups and characters columns can be configured via settings Behavior of groups and characters columns can be configured via settings
""" """
inlines = BaseUserAdmin.inlines + [UserProfileInline] inlines = [UserProfileInline]
ordering = ('username', ) ordering = ('username', )
list_select_related = ('profile__state', 'profile__main_character') list_select_related = ('profile__state', 'profile__main_character')
show_full_result_count = True show_full_result_count = True

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from functools import wraps from functools import wraps

View File

@ -1,6 +1,5 @@
from django.conf.urls import include
from allianceauth.authentication import views from allianceauth.authentication import views
from django.urls import include
from django.urls import re_path from django.urls import re_path
from django.urls import path from django.urls import path

View File

@ -14,6 +14,7 @@ def sync_user_groups(modeladmin, request, queryset):
agc.update_all_states_group_membership() agc.update_all_states_group_membership()
@admin.register(AutogroupsConfig)
class AutogroupsConfigAdmin(admin.ModelAdmin): class AutogroupsConfigAdmin(admin.ModelAdmin):
formfield_overrides = { formfield_overrides = {
models.CharField: {'strip': False} models.CharField: {'strip': False}
@ -36,6 +37,5 @@ class AutogroupsConfigAdmin(admin.ModelAdmin):
return actions return actions
admin.site.register(AutogroupsConfig, AutogroupsConfigAdmin)
admin.site.register(ManagedCorpGroup) admin.site.register(ManagedCorpGroup)
admin.site.register(ManagedAllianceGroup) admin.site.register(ManagedAllianceGroup)

View File

@ -93,7 +93,7 @@ class AutogroupsConfigTestCase(TestCase):
group_qs = Group.objects.filter(pk=group.pk) group_qs = Group.objects.filter(pk=group.pk)
self.assertIn(group, self.member.groups.all()) self.assertIn(group, self.member.groups.all())
self.assertQuerysetEqual(self.member.groups.all(), map(repr, pre_groups | group_qs), ordered=False) self.assertQuerySetEqual(self.member.groups.all(), pre_groups | group_qs, ordered=False)
def test_update_alliance_group_membership_no_main_character(self): def test_update_alliance_group_membership_no_main_character(self):
obj = AutogroupsConfig.objects.create() obj = AutogroupsConfig.objects.create()
@ -172,7 +172,7 @@ class AutogroupsConfigTestCase(TestCase):
group_qs = Group.objects.filter(pk=group.pk) group_qs = Group.objects.filter(pk=group.pk)
self.assertIn(group, self.member.groups.all()) self.assertIn(group, self.member.groups.all())
self.assertQuerysetEqual(self.member.groups.all(), map(repr, pre_groups | group_qs), ordered=False) self.assertQuerySetEqual(self.member.groups.all(), pre_groups | group_qs, ordered=False)
def test_update_corp_group_membership_no_state(self): def test_update_corp_group_membership_no_state(self):
obj = AutogroupsConfig.objects.create(corp_groups=True) obj = AutogroupsConfig.objects.create(corp_groups=True)

View File

@ -2,7 +2,6 @@
import datetime import datetime
from django.db import migrations, models from django.db import migrations, models
from django.utils.timezone import utc
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -15,6 +14,6 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='fatlink', model_name='fatlink',
name='fatdatetime', name='fatdatetime',
field=models.DateTimeField(default=datetime.datetime(2016, 9, 5, 22, 20, 2, 999041, tzinfo=utc)), field=models.DateTimeField(default=datetime.datetime(2016, 9, 5, 22, 20, 2, 999041, tzinfo=datetime.timezone.utc)),
), ),
] ]

View File

@ -10,6 +10,7 @@ class ChoiceInline(admin.TabularInline):
verbose_name_plural = 'Choices (optional)' verbose_name_plural = 'Choices (optional)'
verbose_name= 'Choice' verbose_name= 'Choice'
@admin.register(ApplicationQuestion)
class QuestionAdmin(admin.ModelAdmin): class QuestionAdmin(admin.ModelAdmin):
fieldsets = [ fieldsets = [
(None, {'fields': ['title', 'help_text', 'multi_select']}), (None, {'fields': ['title', 'help_text', 'multi_select']}),
@ -18,6 +19,5 @@ class QuestionAdmin(admin.ModelAdmin):
admin.site.register(Application) admin.site.register(Application)
admin.site.register(ApplicationComment) admin.site.register(ApplicationComment)
admin.site.register(ApplicationQuestion, QuestionAdmin)
admin.site.register(ApplicationForm) admin.site.register(ApplicationForm)
admin.site.register(ApplicationResponse) admin.site.register(ApplicationResponse)

View File

@ -1,3 +1 @@
from .core import notify # noqa: F401 from .core import notify # noqa: F401
default_app_config = 'allianceauth.notifications.apps.NotificationsConfig'

View File

@ -15,18 +15,22 @@ class NotificationAdmin(admin.ModelAdmin):
ordering = ("-timestamp", ) ordering = ("-timestamp", )
search_fields = ["user__username", "user__profile__main_character__character_name"] search_fields = ["user__username", "user__profile__main_character__character_name"]
@admin.display(
ordering="user__profile__main_character__character_name"
)
def _main(self, obj): def _main(self, obj):
try: try:
return obj.user.profile.main_character return obj.user.profile.main_character
except AttributeError: except AttributeError:
return obj.user return obj.user
_main.admin_order_field = "user__profile__main_character__character_name"
@admin.display(
ordering="user__profile__state__name"
)
def _state(self, obj): def _state(self, obj):
return obj.user.profile.state return obj.user.profile.state
_state.admin_order_field = "user__profile__state__name"
def has_change_permission(self, request, obj=None): def has_change_permission(self, request, obj=None):
return False return False

View File

@ -1,9 +1,8 @@
from django.conf.urls import include
from allianceauth import urls from allianceauth import urls
from django.urls import re_path from django.urls import include, path
urlpatterns = [ urlpatterns = [
re_path(r'', include(urls)), path('', include(urls)),
] ]
handler500 = 'allianceauth.views.Generic500Redirect' handler500 = 'allianceauth.views.Generic500Redirect'

View File

@ -66,6 +66,8 @@ class NameFormatConfigAdmin(admin.ModelAdmin):
form = NameFormatConfigForm form = NameFormatConfigForm
list_display = ('service_name', 'get_state_display_string') list_display = ('service_name', 'get_state_display_string')
@admin.display(
description='States'
)
def get_state_display_string(self, obj): def get_state_display_string(self, obj):
return ', '.join([state.name for state in obj.states.all()]) return ', '.join([state.name for state in obj.states.all()])
get_state_display_string.short_description = 'States'

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import re_path from django.urls import re_path
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.template.loader import render_to_string from django.template.loader import render_to_string

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
app_name = 'example' app_name = 'example'

View File

@ -2,8 +2,7 @@ from django.contrib import admin
from .models import Ips4User from .models import Ips4User
@admin.register(Ips4User)
class Ips4UserAdmin(admin.ModelAdmin): class Ips4UserAdmin(admin.ModelAdmin):
list_display = ('user', 'username', 'id') list_display = ('user', 'username', 'id')
search_fields = ('user__username', 'username', 'id') search_fields = ('user__username', 'username', 'id')
admin.site.register(Ips4User, Ips4UserAdmin)

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -36,10 +36,12 @@ class AuthTSgroupAdmin(admin.ModelAdmin):
kwargs['queryset'] = TSgroup.objects.exclude(ts_group_name__in=ReservedGroupName.objects.values_list('name', flat=True)) kwargs['queryset'] = TSgroup.objects.exclude(ts_group_name__in=ReservedGroupName.objects.values_list('name', flat=True))
return super().formfield_for_manytomany(db_field, request, **kwargs) return super().formfield_for_manytomany(db_field, request, **kwargs)
@admin.display(
description='ts groups'
)
def _ts_group(self, obj): def _ts_group(self, obj):
return [x for x in obj.ts_group.all().order_by('ts_group_id')] return [x for x in obj.ts_group.all().order_by('ts_group_id')]
_ts_group.short_description = 'ts groups'
# _ts_group.admin_order_field = 'profile__state' # _ts_group.admin_order_field = 'profile__state'

View File

@ -454,20 +454,16 @@ request.user = MockSuperUser()
class Teamspeak3AdminTestCase(TestCase): class Teamspeak3AdminTestCase(TestCase):
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
cls.site = AdminSite()
cls.admin = AuthTSgroupAdmin(AuthTS, cls.site)
cls.group = Group.objects.create(name='test') cls.group = Group.objects.create(name='test')
cls.ts_group = TSgroup.objects.create(ts_group_id=1, ts_group_name='test') cls.ts_group = TSgroup.objects.create(ts_group_id=1, ts_group_name='test')
def test_field_queryset_no_reserved_names(self): def test_field_queryset_no_reserved_names(self):
"""Ensure all groups are listed when no reserved names""" """Ensure all groups are listed when no reserved names"""
form = self.admin.get_form(request) self.assertQuerySetEqual(AuthTSgroupAdmin(AuthTS, AdminSite()).get_form(request).base_fields['auth_group']._get_queryset(), Group.objects.all())
self.assertQuerysetEqual(form.base_fields['auth_group']._get_queryset(), Group.objects.all()) self.assertQuerySetEqual(AuthTSgroupAdmin(AuthTS, AdminSite()).get_form(request).base_fields['ts_group']._get_queryset(), TSgroup.objects.all())
self.assertQuerysetEqual(form.base_fields['ts_group']._get_queryset(), TSgroup.objects.all())
def test_field_queryset_reserved_names(self): def test_field_queryset_reserved_names(self):
"""Ensure reserved group names are filtered out""" """Ensure reserved group names are filtered out"""
ReservedGroupName.objects.bulk_create([ReservedGroupName(name='test', reason='tests', created_by='Bob')]) ReservedGroupName.objects.bulk_create([ReservedGroupName(name='test', reason='tests', created_by='Bob')])
form = self.admin.get_form(request) self.assertQuerySetEqual(AuthTSgroupAdmin(AuthTS, AdminSite()).get_form(request).base_fields['auth_group']._get_queryset(), Group.objects.none())
self.assertQuerysetEqual(form.base_fields['auth_group']._get_queryset(), Group.objects.none()) self.assertQuerySetEqual(AuthTSgroupAdmin(AuthTS, AdminSite()).get_form(request).base_fields['ts_group']._get_queryset(), TSgroup.objects.none())
self.assertQuerysetEqual(form.base_fields['ts_group']._get_queryset(), TSgroup.objects.none())

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from django.urls import path from django.urls import path
from . import views from . import views

View File

@ -1,4 +1,4 @@
from django.conf.urls import include from django.urls import include
from allianceauth.hooks import get_hooks from allianceauth.hooks import get_hooks
from django.urls import path from django.urls import path

View File

@ -1,7 +1,7 @@
from django.urls import path from django.urls import path
import esi.urls import esi.urls
from django.conf.urls import include from django.urls import include
from django.contrib import admin from django.contrib import admin
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView

View File

@ -1,5 +1,5 @@
FROM python:3.9-slim FROM python:3.11-slim
ARG AUTH_VERSION=v3.4.0 ARG AUTH_VERSION=v4.0.0a1
ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION} ARG AUTH_PACKAGE=allianceauth==${AUTH_VERSION}
ENV VIRTUAL_ENV=/opt/venv ENV VIRTUAL_ENV=/opt/venv
ENV AUTH_USER=allianceauth ENV AUTH_USER=allianceauth

View File

@ -17,7 +17,7 @@ services:
restart: unless-stopped restart: unless-stopped
nginx: nginx:
image: nginx:1.21 image: nginx:1.25
restart: always restart: always
volumes: volumes:
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
@ -26,7 +26,7 @@ services:
- allianceauth - allianceauth
redis: redis:
image: redis:6.2 image: redis:7.0
command: redis-server command: redis-server
restart: always restart: always
volumes: volumes:
@ -52,7 +52,7 @@ services:
- auth_mysql - auth_mysql
grafana: grafana:
image: grafana/grafana-oss:8.5.22 image: grafana/grafana-oss:9.5.2
restart: always restart: always
depends_on: depends_on:
- auth_mysql - auth_mysql

View File

@ -7,11 +7,12 @@ long_description_content_type = text/markdown
author = Alliance Auth author = Alliance Auth
author_email = adarnof@gmail.com author_email = adarnof@gmail.com
license = GPL-2.0 license = GPL-2.0
license_file = LICENSE license_files = LICENSE
classifiers = classifiers =
Environment :: Web Environment Environment :: Web Environment
Framework :: Django Framework :: Django
Framework :: Django :: 4 Framework :: Django :: 4
Framework :: Django :: 4.2
Intended Audience :: Developers Intended Audience :: Developers
License :: OSI Approved :: GNU General Public License v2 (GPLv2) License :: OSI Approved :: GNU General Public License v2 (GPLv2)
Operating System :: POSIX :: Linux Operating System :: POSIX :: Linux
@ -39,7 +40,7 @@ install_requires =
beautifulsoup4 beautifulsoup4
celery>=5.2.0,<6 celery>=5.2.0,<6
celery-once>=3.0.1 celery-once>=3.0.1
django>=4.0.9,<4.1.0 django>=4.2,<5
django-bootstrap-form django-bootstrap-form
django-celery-beat>=2.3.0 django-celery-beat>=2.3.0
django-esi>=4.0.1 django-esi>=4.0.1

View File

@ -2,7 +2,7 @@
isolated_build = True isolated_build = True
skipsdist = true skipsdist = true
usedevelop = true usedevelop = true
envlist = py{38,39,310,311,py}-{all,core}, docs envlist = py{38,39,310,311,312,py}-{all,core}, docs
[testenv] [testenv]
setenv = setenv =
@ -13,6 +13,7 @@ basepython =
py39: python3.9 py39: python3.9
py310: python3.10 py310: python3.10
py311: python3.11 py311: python3.11
py312: python3.12
pypy: pypy3 pypy: pypy3
deps= deps=
coverage coverage
@ -25,7 +26,7 @@ commands =
[testenv:docs] [testenv:docs]
description = invoke sphinx-build to build the HTML docs description = invoke sphinx-build to build the HTML docs
basepython = python3.9 basepython = python3.11
skip_install = True skip_install = True
deps = -r{toxinidir}/docs/requirements.txt deps = -r{toxinidir}/docs/requirements.txt
install_command = python -I -m pip install {opts} {packages} install_command = python -I -m pip install {opts} {packages}