Compare commits

...

9 Commits

Author SHA1 Message Date
Ariel Rin
def6431052 Version Bump 2.14.0 2022-07-11 14:27:49 +10:00
Ariel Rin
22a270aedb Merge branch 'filterdropdown-backwards-compatibility' into 'master'
Add filterdropdown bundle to AA2 to ensure backwards compatibility

See merge request allianceauth/allianceauth!1437
2022-07-11 04:15:25 +00:00
Peter Pfeufer
c930f7bbeb Also adds timers.js, eve-time.js and refresh_notifications.js
As these seem to be used in some apps as well
2022-07-09 15:57:43 +02:00
Peter Pfeufer
64ee273953 Add filterdropdown bundle to AA2 to ensure backwards compatibility 2022-07-09 13:43:05 +02:00
Ariel Rin
3706a1aedf Merge branch 'improve-autodocs-for-models' into 'master'
Improve autodocs for models & more

See merge request allianceauth/allianceauth!1435
2022-07-07 07:38:58 +00:00
Ariel Rin
47f1b77320 Merge branch 'consolidate-redis-client-access' into 'master'
Ensure backwards compatibility when fetching a redis client

See merge request allianceauth/allianceauth!1428
2022-07-07 07:37:21 +00:00
Erik Kalkoken
8dec242a93 Ensure backwards compatibility when fetching a redis client 2022-07-07 07:37:21 +00:00
ErikKalkoken
2ff200c566 Refer to django-esi docs 2022-06-27 13:43:45 +02:00
ErikKalkoken
091a2637ea Add extension to improve autodocs for Django models & enable source links 2022-06-27 13:41:15 +02:00
25 changed files with 117 additions and 73 deletions

View File

@@ -1,7 +1,7 @@
# This will make sure the app is always imported when # This will make sure the app is always imported when
# Django starts so that shared_task will use this app. # Django starts so that shared_task will use this app.
__version__ = '2.13.0' __version__ = '2.14.0'
__title__ = 'Alliance Auth' __title__ = 'Alliance Auth'
__url__ = 'https://gitlab.com/allianceauth/allianceauth' __url__ = 'https://gitlab.com/allianceauth/allianceauth'
NAME = f'{__title__} v{__version__}' NAME = f'{__title__} v{__version__}'

View File

@@ -5,7 +5,7 @@ from typing import List, Optional
from pytz import utc from pytz import utc
from redis import Redis, RedisError from redis import Redis, RedisError
from django.core.cache import cache from allianceauth.utils.cache import get_redis_client
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -39,7 +39,7 @@ class EventSeries:
_ROOT_KEY = "ALLIANCEAUTH_EVENT_SERIES" _ROOT_KEY = "ALLIANCEAUTH_EVENT_SERIES"
def __init__(self, key_id: str, redis: Redis = None) -> None: def __init__(self, key_id: str, redis: Redis = None) -> None:
self._redis = cache.get_master_client() if not redis else redis self._redis = get_redis_client() if not redis else redis
try: try:
if not self._redis.ping(): if not self._redis.ping():
raise RuntimeError() raise RuntimeError()

View File

@@ -18,7 +18,7 @@ MODULE_PATH = "allianceauth.authentication.task_statistics.event_series"
class TestEventSeries(TestCase): class TestEventSeries(TestCase):
def test_should_abort_without_redis_client(self): def test_should_abort_without_redis_client(self):
# when # when
with patch(MODULE_PATH + ".cache.get_master_client") as mock: with patch(MODULE_PATH + ".get_redis_client") as mock:
mock.return_value = None mock.return_value = None
events = EventSeries("dummy") events = EventSeries("dummy")
# then # then
@@ -27,7 +27,7 @@ class TestEventSeries(TestCase):
def test_should_disable_itself_if_redis_not_available_1(self): def test_should_disable_itself_if_redis_not_available_1(self):
# when # when
with patch(MODULE_PATH + ".cache.get_master_client") as mock_get_master_client: with patch(MODULE_PATH + ".get_redis_client") as mock_get_master_client:
mock_get_master_client.return_value.ping.side_effect = RedisError mock_get_master_client.return_value.ping.side_effect = RedisError
events = EventSeries("dummy") events = EventSeries("dummy")
# then # then
@@ -36,7 +36,7 @@ class TestEventSeries(TestCase):
def test_should_disable_itself_if_redis_not_available_2(self): def test_should_disable_itself_if_redis_not_available_2(self):
# when # when
with patch(MODULE_PATH + ".cache.get_master_client") as mock_get_master_client: with patch(MODULE_PATH + ".get_redis_client") as mock_get_master_client:
mock_get_master_client.return_value.ping.return_value = False mock_get_master_client.return_value.ping.return_value = False
events = EventSeries("dummy") events = EventSeries("dummy")
# then # then

View File

@@ -8,7 +8,7 @@ from uuid import uuid1
from redis import Redis from redis import Redis
import requests import requests
from django.core.cache import caches from allianceauth.utils.cache import get_redis_client
from allianceauth import __title__ as AUTH_TITLE, __url__, __version__ from allianceauth import __title__ as AUTH_TITLE, __url__, __version__
@@ -103,8 +103,7 @@ class DiscordClient:
self._access_token = str(access_token) self._access_token = str(access_token)
self._is_rate_limited = bool(is_rate_limited) self._is_rate_limited = bool(is_rate_limited)
if not redis: if not redis:
default_cache = caches['default'] self._redis = get_redis_client()
self._redis = default_cache.get_master_client()
if not isinstance(self._redis, Redis): if not isinstance(self._redis, Redis):
raise RuntimeError( raise RuntimeError(
'This class requires a Redis client, but none was provided ' 'This class requires a Redis client, but none was provided '

View File

@@ -85,29 +85,18 @@ class TestBasicsAndHelpers(TestCase):
client = DiscordClient(TEST_BOT_TOKEN, mock_redis, is_rate_limited=True) client = DiscordClient(TEST_BOT_TOKEN, mock_redis, is_rate_limited=True)
self.assertTrue(client.is_rate_limited) self.assertTrue(client.is_rate_limited)
@patch(MODULE_PATH + '.caches') def test_use_default_redis_if_none_provided(self):
def test_use_default_redis_if_none_provided(self, mock_caches):
my_redis = MagicMock(spec=Redis)
mock_default_cache = MagicMock(**{'get_master_client.return_value': my_redis})
my_dict = {'default': mock_default_cache}
mock_caches.__getitem__.side_effect = my_dict.__getitem__
client = DiscordClient(TEST_BOT_TOKEN) client = DiscordClient(TEST_BOT_TOKEN)
self.assertTrue(mock_default_cache.get_master_client.called) self.assertIsInstance(client._redis, Redis)
self.assertEqual(client._redis, my_redis)
@patch(MODULE_PATH + '.caches')
def test_raise_exception_if_default_cache_is_not_redis(self, mock_caches):
my_redis = MagicMock()
mock_default_cache = MagicMock(**{'get_master_client.return_value': my_redis})
my_dict = {'default': mock_default_cache}
mock_caches.__getitem__.side_effect = my_dict.__getitem__
@patch(MODULE_PATH + '.get_redis_client')
def test_raise_exception_if_redis_client_not_found(self, mock_get_redis_client):
# given
mock_get_redis_client.return_value = None
# when
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
DiscordClient(TEST_BOT_TOKEN) DiscordClient(TEST_BOT_TOKEN)
self.assertTrue(mock_default_cache.get_master_client.called)
@requests_mock.Mocker() @requests_mock.Mocker()
class TestOtherMethods(TestCase): class TestOtherMethods(TestCase):

View File

@@ -35,17 +35,17 @@ import logging
from uuid import uuid1 from uuid import uuid1
import random import random
from django.core.cache import caches
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from allianceauth.services.modules.discord.models import DiscordUser from allianceauth.services.modules.discord.models import DiscordUser
from allianceauth.utils.cache import get_redis_client
logger = logging.getLogger('allianceauth') logger = logging.getLogger('allianceauth')
MAX_RUNS = 3 MAX_RUNS = 3
def clear_cache(): def clear_cache():
default_cache = caches['default'] redis = get_redis_client()
redis = default_cache.get_master_client()
redis.flushall() redis.flushall()
logger.info('Cache flushed') logger.info('Cache flushed')

View File

@@ -14,7 +14,6 @@ from requests.exceptions import HTTPError
import requests_mock import requests_mock
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.core.cache import caches
from django.shortcuts import reverse from django.shortcuts import reverse
from django.test import TransactionTestCase, TestCase from django.test import TransactionTestCase, TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
@@ -23,6 +22,7 @@ from allianceauth.authentication.models import State
from allianceauth.eveonline.models import EveCharacter from allianceauth.eveonline.models import EveCharacter
from allianceauth.notifications.models import Notification from allianceauth.notifications.models import Notification
from allianceauth.tests.auth_utils import AuthUtils from allianceauth.tests.auth_utils import AuthUtils
from allianceauth.utils.cache import get_redis_client
from . import ( from . import (
TEST_GUILD_ID, TEST_GUILD_ID,
@@ -87,8 +87,7 @@ remove_guild_member_request = DiscordRequest(
def clear_cache(): def clear_cache():
default_cache = caches['default'] redis = get_redis_client()
redis = default_cache.get_master_client()
redis.flushall() redis.flushall()
logger.info('Cache flushed') logger.info('Cache flushed')
@@ -109,7 +108,6 @@ def reset_testdata():
class TestServiceFeatures(TransactionTestCase): class TestServiceFeatures(TransactionTestCase):
fixtures = ['disable_analytics.json'] fixtures = ['disable_analytics.json']
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
super().setUpClass() super().setUpClass()

View File

@@ -0,0 +1,3 @@
{% load static %}
<script src="{% static 'js/eve-time.js' %}"></script>

View File

@@ -0,0 +1,3 @@
{% load static %}
<script type="application/javascript" src="{% static 'js/filterDropDown/filterDropDown.min.js' %}">

View File

@@ -0,0 +1,3 @@
{% load static %}
<script src="{% static 'js/refresh_notifications.js' %}"></script>

View File

@@ -0,0 +1,3 @@
{% load static %}
<script src="{% static 'js/timers.js' %}"></script>

View File

View File

@@ -0,0 +1,21 @@
from redis import Redis
from django.core.cache import caches
try:
import django_redis
except ImportError:
django_redis = None
def get_redis_client() -> Redis:
"""Get the configured redis client used by Django for caching.
This function is a wrapper designed to work for both AA2 and AA3
and should always be used to ensure backwards compatibility.
"""
try:
return django_redis.get_redis_connection("default")
except AttributeError:
default_cache = caches["default"]
return default_cache.get_master_client()

View File

View File

@@ -0,0 +1,39 @@
from unittest.mock import MagicMock, patch
from django.test import TestCase
from allianceauth.utils.cache import get_redis_client
MODULE_PATH = "allianceauth.utils.cache"
class RedisClientStub:
"""Substitute for a Redis client."""
pass
class TestGetRedisClient(TestCase):
def test_should_work_with_aa2_api(self):
# given
mock_django_cache = MagicMock()
mock_django_cache.get_master_client.return_value = RedisClientStub()
# when
with patch(MODULE_PATH + ".django_redis", None), patch.dict(
MODULE_PATH + ".caches", {"default": mock_django_cache}
):
client = get_redis_client()
# then
self.assertIsInstance(client, RedisClientStub)
def test_should_work_with_aa3_api(self):
# given
mock_django_redis = MagicMock()
mock_django_redis.get_redis_connection.return_value = RedisClientStub()
# when
with patch(MODULE_PATH + ".django_redis", mock_django_redis), patch.dict(
MODULE_PATH + ".caches", {"default": None}
):
client = get_redis_client()
# then
self.assertIsInstance(client, RedisClientStub)

View File

@@ -1,7 +1,7 @@
PROTOCOL=https:// PROTOCOL=https://
AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN% AUTH_SUBDOMAIN=%AUTH_SUBDOMAIN%
DOMAIN=%DOMAIN% DOMAIN=%DOMAIN%
AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v2.13 AA_DOCKER_TAG=registry.gitlab.com/allianceauth/allianceauth/auth:v2.14.0
# Nginx Proxy Manager # Nginx Proxy Manager
PROXY_HTTP_PORT=80 PROXY_HTTP_PORT=80

View File

@@ -1,5 +1,5 @@
FROM python:3.9-slim FROM python:3.9-slim
ARG AUTH_VERSION=2.13.0 ARG AUTH_VERSION=2.14.0
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

@@ -8,7 +8,7 @@ You should have the following available on the system you are using to set this
## Setup Guide ## Setup Guide
1. run `bash <(curl -s https://gitlab.com/allianceauth/allianceauth/-/raw/v2.11.x/docker/scripts/download.sh)`. This will download all the files you need to install auth and place them in a directory named `aa-docker`. Feel free to rename/move this folder. 1. run `bash <(curl -s https://gitlab.com/allianceauth/allianceauth/-/raw/v2.14.x/docker/scripts/download.sh)`. This will download all the files you need to install auth and place them in a directory named `aa-docker`. Feel free to rename/move this folder.
1. run `./scripts/prepare-env.sh` to set up your environment 1. run `./scripts/prepare-env.sh` to set up your environment
1. (optional) Change `PROTOCOL` to `http://` if not using SSL in `.env` 1. (optional) Change `PROTOCOL` to `http://` if not using SSL in `.env`
1. run `docker-compose --env-file=.env up -d` (NOTE: if this command hangs, follow the instructions [here](https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged)) 1. run `docker-compose --env-file=.env up -d` (NOTE: if this command hangs, follow the instructions [here](https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged))

View File

@@ -44,6 +44,8 @@ extensions = [
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx.ext.napoleon', 'sphinx.ext.napoleon',
'recommonmark', 'recommonmark',
'sphinxcontrib_django2',
'sphinx.ext.viewcode',
] ]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.

View File

@@ -4,36 +4,4 @@ django-esi
The django-esi package provides an interface for easy access to the ESI. The django-esi package provides an interface for easy access to the ESI.
Location: ``esi`` This is an external package. Please see `here <https://django-esi.readthedocs.io/en/latest/>`_ for it's documentation.
This is an external package. Please also see `here <https://gitlab.com/allianceauth/django-esi>`_ for it's official documentation.
clients
===========
.. automodule:: esi.clients
:members: esi_client_factory
:undoc-members:
decorators
===========
.. automodule:: esi.decorators
:members:
:undoc-members:
errors
===========
.. automodule:: esi.errors
:members:
:undoc-members:
models
===========
.. automodule:: esi.models
:members: Scope, Token
:exclude-members: objects, provider
:undoc-members:

View File

@@ -11,5 +11,4 @@ models
.. automodule:: allianceauth.eveonline.models .. automodule:: allianceauth.eveonline.models
:members: :members:
:exclude-members: objects, provider :exclude-members: DoesNotExist, MultipleObjectsReturned
:undoc-members:

View File

@@ -11,4 +11,5 @@ To reduce redundancy and help speed up development we encourage developers to ut
eveonline eveonline
notifications notifications
testutils testutils
utils
``` ```

View File

@@ -13,7 +13,8 @@ models
=========== ===========
.. autoclass:: allianceauth.notifications.models.Notification .. autoclass:: allianceauth.notifications.models.Notification
:members: Level, mark_viewed, set_level :members:
:exclude-members: DoesNotExist, MultipleObjectsReturned, save
managers managers
=========== ===========

View File

@@ -0,0 +1,14 @@
=============================
utils
=============================
Utilities and helper functions.
Location: ``allianceauth.utils``
cache
===========
.. automodule:: allianceauth.utils.cache
:members:
:undoc-members:

View File

@@ -3,6 +3,7 @@ sphinx>=3.2.1,<4.0.0
sphinx_rtd_theme==0.5.0 sphinx_rtd_theme==0.5.0
recommonmark==0.6.0 recommonmark==0.6.0
Jinja2<3.1 Jinja2<3.1
sphinxcontrib-django2
# Autodoc dependencies # Autodoc dependencies
django>=3.2,<4.0.0 django>=3.2,<4.0.0