Browse Source

Early groundwork for new database settings proxy

rafalp 6 years ago
parent
commit
4d6381002c

+ 2 - 0
misago/conf/__init__.py

@@ -1,3 +1,5 @@
 from .gateway import settings, db_settings  # noqa
 
+CACHE_NAME = "settings"
+
 default_app_config = 'misago.conf.apps.MisagoConfConfig'

+ 70 - 0
misago/conf/databasesettings.py

@@ -0,0 +1,70 @@
+from django.core.cache import cache
+
+from . import CACHE_NAME
+from .models import Setting
+
+
+class DatabaseSettings:
+    _overrides = {}
+
+    def __init__(self, cache_versions):
+        cache_name = get_cache_name(cache_versions)
+        self._settings = cache.get(cache_name)
+        if self._settings is None:
+            self._settings = get_settings_from_db()
+            cache.set(cache_name, self._settings)
+
+    def get_public_settings(self):
+        public_settings = {}
+        for name, setting in self._settings.items():
+            if setting["is_public"]:
+                public_settings[name] = setting["value"]
+        return public_settings
+
+    def get_lazy_setting_value(self, setting):
+        try:
+            if self._settings[setting]["is_lazy"]:
+                if setting in self._overrides:
+                    return self._overrides[setting]
+                if not self._settings[setting].get("real_value"):
+                    real_value = Setting.objects.get(setting=setting).value
+                    self._settings[setting]["real_value"] = real_value
+                return self._settings[setting]["real_value"]
+            raise ValueError("Setting %s is not lazy" % setting)
+        except (KeyError, Setting.DoesNotExist):
+            raise AttributeError("Setting %s is not defined" % setting)
+
+    def __getattr__(self, setting):
+        if setting in self._overrides:
+            return self._overrides[setting]
+        return self._settings[setting]["value"]
+
+    @classmethod
+    def override_settings(cls, overrides):
+        cls._overrides = overrides
+
+    @classmethod
+    def remove_overrides(cls):
+        cls._overrides = {}
+
+
+def get_cache_name(cache_versions):
+    return "%s_%s" % (CACHE_NAME, cache_versions[CACHE_NAME])
+
+
+def get_settings_from_db():
+    settings = {}
+    for setting in Setting.objects.iterator():
+        if setting.is_lazy:
+            settings[setting.setting] = {
+                'value': True if setting.value else None,
+                'is_lazy': setting.is_lazy,
+                'is_public': setting.is_public,
+            }
+        else:
+            settings[setting.setting] = {
+                'value': setting.value,
+                'is_lazy': setting.is_lazy,
+                'is_public': setting.is_public,
+            }
+    return settings

+ 4 - 3
misago/conf/dbsettings.py

@@ -1,10 +1,11 @@
-from misago.core import threadstore
+from django.core.cache import cache
 
+from misago.core import threadstore
 
 CACHE_KEY = 'misago_db_settings'
 
 
-class DBSettings(object):
+class DBSettingsDeprecated(object):
     def __init__(self):
         self._settings = self._read_cache()
         self._overrides = {}
@@ -85,7 +86,7 @@ class _DBSettingsGateway(object):
     def get_db_settings(self):
         dbsettings = threadstore.get(CACHE_KEY)
         if not dbsettings:
-            dbsettings = DBSettings()
+            dbsettings = DBSettingsDeprecated()
             threadstore.set(CACHE_KEY, dbsettings)
         return dbsettings
 

+ 17 - 0
misago/conf/migrations/0002_cache_version.py

@@ -0,0 +1,17 @@
+# Generated by Django 1.11.16 on 2018-12-02 15:54
+from django.db import migrations
+
+from misago.cache.operations import StartCacheVersioning
+
+from misago.conf import CACHE_NAME
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('misago_conf', '0001_initial'),
+    ]
+
+    operations = [
+        StartCacheVersioning(CACHE_NAME)
+    ]

+ 21 - 0
misago/conf/tests/__init__.py

@@ -0,0 +1,21 @@
+from functools import wraps
+
+from misago.conf.databasesettings import DatabaseSettings
+
+
+class OverrideDatabaseSettings:
+    def __init__(self, **settings):
+        self._overrides = settings
+
+    def __enter__(self):
+        DatabaseSettings.override_settings(self._overrides)
+
+    def __exit__(self, *_):
+        DatabaseSettings.remove_overrides()
+
+    def __call__(self, f):
+        @wraps(f)
+        def test_function_wrapper(*args, **kwargs):
+            with self as context:
+                return f(*args, **kwargs)
+        return test_function_wrapper

+ 5 - 0
misago/conf/tests/test_getting_setting_value.py

@@ -0,0 +1,5 @@
+from django.test import TestCase
+
+
+class GettingSettingValueTests(TestCase):
+    pass

+ 16 - 0
misago/conf/tests/test_overriding_db_settings.py

@@ -0,0 +1,16 @@
+from django.test import TestCase
+
+from misago.conf import CACHE_NAME
+from misago.conf.tests import OverrideDatabaseSettings
+from misago.conf.databasesettings import DatabaseSettings
+
+
+class OverrideDatabaseSettingsTests(TestCase):
+    def test_as_context_manager(self):
+        settings = DatabaseSettings({CACHE_NAME: "abcdefgh"})
+        assert settings.forum_name == "Misago"
+
+        with OverrideDatabaseSettings(forum_name="Overrided"):
+            assert settings.forum_name == "Overrided"
+
+        assert settings.forum_name == "Misago"

+ 0 - 0
misago/conf/tests/test_settings_middleware.py