Coverage for src/mesh/app_settings.py: 75%
51 statements
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-28 07:45 +0000
« prev ^ index » next coverage.py v7.7.0, created at 2025-04-28 07:45 +0000
1import os
2from datetime import timedelta
3from enum import Enum, unique
4from typing import Any
6from django.conf import settings
7from django.core.exceptions import ImproperlyConfigured
10@unique
11class BlindMode(Enum):
12 NO_BLIND = "no_blind"
13 SINGLE_BLIND = "single_blind"
14 DOUBLE_BLIND = "double_blind"
17class AppSettings:
18 """Wrapper for django settings related to this application."""
20 REQUIRED_SETTINGS = ["FILES_DIRECTORY"]
22 def __init__(self):
23 self.prefix = "MESH_"
24 for setting in self.REQUIRED_SETTINGS:
25 if self._setting(setting, "__NOT_CONFIGURED__") == "__NOT_CONFIGURED__": 25 ↛ 26line 25 didn't jump to line 26 because the condition on line 25 was never true
26 raise ImproperlyConfigured(
27 f"`mesh` - You must set the following setting(s): {setting}"
28 )
29 if not os.path.isdir(self.FILES_DIRECTORY): 29 ↛ exitline 29 didn't return from function '__init__' because the condition on line 29 was always true
30 try:
31 os.makedirs(self.FILES_DIRECTORY, mode=511)
32 except OSError:
33 raise ImproperlyConfigured(
34 f"`mesh` - The provided FILES_DIRECTORY is not an accessible directory and cannot be created automatically: {self.FILES_DIRECTORY}"
35 )
37 def _setting(self, name: str, default: Any = None):
38 """
39 Gets the provided setting with the app prefix (see `self.prefix`).
41 Params:
42 - `name`: The name of the setting.
43 - `default`: Fallback if the settings is not defined.
44 """
45 return getattr(settings, self.prefix + name, default)
47 @property
48 def ENABLED_ROLES(self) -> list[str]:
49 """
50 List of role codes enabled for this application.
51 Defaults to `["author", "journal_manager"]`.
52 """
53 return self._setting("ENABLED_ROLES", ["author", "reviewer", "editor", "journal_manager"])
55 @property
56 def BLIND_MODE(self) -> BlindMode:
57 """
58 Return the blind mode of the application.
59 """
60 blind_mode = self._setting("BLIND_MODE", BlindMode.SINGLE_BLIND.value)
61 try:
62 return BlindMode(blind_mode)
63 except ValueError:
64 raise ImproperlyConfigured(
65 f"Invalid setting value for BLIND_MODE: {blind_mode}. "
66 f"Available values are: {[b.value for b in BlindMode]}."
67 )
69 @property
70 def FILES_DIRECTORY(self) -> str:
71 """
72 Directory used to store all user files.
73 Files are served using django-sendfile package (XSendFile with Apache).
74 This should lie outside of Django directory.
75 The directory is automatically created on startup if required.
76 """
77 return self._setting("FILES_DIRECTORY")
79 @property
80 def USER_TOKEN_EXPIRATION_DAYS(self) -> timedelta:
81 """
82 Expiration time (in days) when an user token is delivered.
83 """
84 return timedelta(days=self._setting("USER_TOKEN_EXPIRATION_DAYS", 180))
86 @property
87 def EMAIL_PREFIX(self) -> str:
88 """
89 Prefix for every e-mail manually sent by the MESH application.
90 Defaults to `[MESH] `.
91 """
92 prefix = self._setting("EMAIL_PREFIX", "[MESH] ")
93 if prefix[-1] != " ":
94 prefix = f"{prefix} "
95 return prefix
97 @property
98 def JOURNAL_EMAIL_CONTACT(self) -> str:
99 return self._setting("JOURNAL_EMAIL_CONTACT", "")
102app_settings = AppSettings()