Skip to content

Commit

Permalink
Raise RuntimeError if accessing a config before it's loaded
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkLark86 committed Jun 26, 2024
1 parent 43487b8 commit ff1d826
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
19 changes: 18 additions & 1 deletion superdesk/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,26 @@

from typing import Dict, Any, Optional, TypeVar, Type, Union

from pydantic import BaseModel, ConfigDict, ValidationError
from pydantic import BaseModel, ConfigDict


class ConfigModel(BaseModel):
model_config = ConfigDict(validate_assignment=True)
_loaded: bool = False

def __eq__(self, other: Any) -> bool:
# We only support checking config instances vs other config instances
return False if not isinstance(other, ConfigModel) else self.__dict__ == other.__dict__

def __getattribute__(self, name: str):
# Allow unrestricted access to private and pydantic private attributes
if name.startswith("_") or name.startswith("model_"):
return BaseModel.__getattribute__(self, name)

if not self._loaded:
raise RuntimeError(f"Config {self.__class__} not loaded, while accessing attribute '{name}'")

return BaseModel.__getattribute__(self, name)


ConfigClassType = TypeVar("ConfigClassType", bound=ConfigModel)
Expand Down Expand Up @@ -54,6 +69,7 @@ def get_config_instance(
config_instance = config_class.model_validate(_get_config_dict(app_config, config_class, prefix))
if freeze:
config_instance.model_config["frozen"] = True
config_instance._loaded = True
return config_instance


Expand All @@ -76,5 +92,6 @@ def load_config_instance(
setattr(config_instance, key, val)

config_instance.model_config["frozen"] = freeze
config_instance._loaded = True

return config_instance
10 changes: 7 additions & 3 deletions tests/core/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@


class ConfigTestCase(unittest.TestCase):
def test_restricted_access_to_config_if_not_loaded(self):
config = module_with_config.ModuleConfig()
with self.assertRaises(RuntimeError):
self.assertEqual(config.default_string, "test-default")
config._loaded = True
self.assertEqual(config.default_string, "test-default")

def test_default_values(self):
# Test default values
self.assertEqual(
Expand Down Expand Up @@ -83,10 +90,7 @@ async def asyncSetUp(self, force: bool = False):
await super().asyncSetUp()

def test_module_config(self):
print(self.app_config)
self.setupApp()
print(module_with_config.ModuleConfig())
print(module_with_config.config)
self.assertEqual(module_with_config.ModuleConfig(), module_with_config.config)

def test_app_fails_to_start_with_invalid_config(self):
Expand Down

0 comments on commit ff1d826

Please sign in to comment.