Skip to content
Commits on Source (6)
......@@ -6,6 +6,14 @@ All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog`_,
and this project adheres to `Semantic Versioning`_.
2.8.1`_ - 2022-03-13
--------------------
Changed
~~~~~~~
* Official apps can now override any setting
`2.8`_ - 2022-03-11
-------------------
......@@ -784,3 +792,4 @@ Fixed
.. _2.7.3: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.3
.. _2.7.4: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.4
.. _2.8: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.8
.. _2.8.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.8.1
......@@ -7,7 +7,12 @@ from django.utils.translation import gettext_lazy as _
from dynaconf import LazySettings
from .util.core_helpers import get_app_packages, merge_app_settings, monkey_patch
from .util.core_helpers import (
get_app_packages,
get_app_settings_overrides,
merge_app_settings,
monkey_patch,
)
monkey_patch()
......@@ -1007,3 +1012,5 @@ merge_app_settings("SHELL_PLUS_DONT_LOAD", SHELL_PLUS_DONT_LOAD)
# Add django-cleanup after all apps to ensure that it gets all signals as last app
INSTALLED_APPS.append("django_cleanup.apps.CleanupConfig")
locals().update(get_app_settings_overrides())
......@@ -3,6 +3,7 @@ from datetime import datetime, timedelta
from importlib import import_module, metadata
from itertools import groupby
from operator import itemgetter
from types import ModuleType
from typing import Any, Callable, Dict, Optional, Sequence, Union
from warnings import warn
......@@ -59,9 +60,31 @@ def dt_show_toolbar(request: HttpRequest) -> bool:
return False
def get_app_packages() -> Sequence[str]:
def get_app_packages(only_official: bool = False) -> Sequence[str]:
"""Find all registered apps from the setuptools entrypoint."""
return [f"{ep.module}.{ep.attr}" for ep in metadata.entry_points().get("aleksis.app", [])]
apps = []
for ep in metadata.entry_points().get("aleksis.app", []):
path = f"{ep.module}.{ep.attr}"
if path.startswith("aleksis.apps.") or not only_official:
apps.append(path)
return apps
def get_app_settings_module(app: str) -> Optional[ModuleType]:
"""Get the settings module of an app."""
pkg = ".".join(app.split(".")[:-2])
mod_settings = None
while "." in pkg:
try:
return import_module(pkg + ".settings")
except ImportError:
# Import errors are non-fatal.
pkg = ".".join(pkg.split(".")[:-1])
# The app does not have settings
return None
def merge_app_settings(
......@@ -77,18 +100,8 @@ def merge_app_settings(
potentially malicious apps!
"""
for app in get_app_packages():
pkg = ".".join(app.split(".")[:-2])
mod_settings = None
while "." in pkg:
try:
mod_settings = import_module(pkg + ".settings")
except ImportError:
# Import errors are non-fatal.
pkg = ".".join(pkg.split(".")[:-1])
continue
break
mod_settings = get_app_settings_module(app)
if not mod_settings:
# The app does not have settings
continue
app_setting = getattr(mod_settings, setting, None)
......@@ -109,6 +122,26 @@ def merge_app_settings(
raise TypeError("Only dict and list settings can be merged.")
def get_app_settings_overrides() -> dict[str, Any]:
"""Get app settings overrides.
Official apps (those under the ``aleksis.apps` namespace) can override
or add settings by listing them in their ``settings.overrides``.
"""
overrides = {}
for app in get_app_packages(True):
mod_settings = get_app_settings_module(app)
if not mod_settings:
continue
if hasattr(mod_settings, "overrides"):
for name in mod_settings.overrides:
overrides[name] = getattr(mod_settings, name)
return overrides
def get_site_preferences():
"""Get the preferences manager of the current site."""
from django.contrib.sites.models import Site # noqa
......
......@@ -31,7 +31,7 @@ author = "The AlekSIS Team"
# The short X.Y version
version = "2.8"
# The full version, including alpha/beta/rc tags
release = "2.8"
release = "2.8.1"
# -- General configuration ---------------------------------------------------
......
......@@ -3,9 +3,15 @@ Merging of app settings
AlekSIS provides features to merge app settings into main ``settings.py``.
Third-party apps can only add values to some select existing settings.
Official apps (those under the ``aleksis.apps.`` namespace) can mark any
setting for overriding.
Currently mergable settings
---------------------------
The following settings can be amended by any app:
* INSTALLED_APPS
* DATABASES
* YARN_INSTALLED_APPS
......@@ -24,3 +30,13 @@ the following into your ``settings.py``::
"PORT": 5432,
}
}
Overriding any setting
----------------------
Official apps only (currently) can override any setting, but need to explicitly
mark it by listing it in a list called ``overrides`` in their ``settings.py``::
PAYMENT_MODEL = "tezor.Invoice"
overrides = ["PAYMENT_MODEL"]
[tool.poetry]
name = "AlekSIS-Core"
version = "2.8"
version = "2.8.1"
packages = [
{ include = "aleksis" }
]
......