Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from loguru import logger

from commonwealth.settings.bases.pydantic_base import PydanticSettings
from commonwealth.settings.exceptions import SettingsFromTheFuture


class PydanticManager:
Expand Down Expand Up @@ -128,10 +127,12 @@ def get_settings_version_from_filename(filename: pathlib.Path) -> int:
self._settings = PydanticManager.load_from_file(self.settings_type, valid_file)
logger.debug(f"Using {valid_file} as settings source")
return
except SettingsFromTheFuture as exception:
except Exception as exception:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Catching Exception may mask unrelated errors.

Catching Exception instead of SettingsFromTheFuture may hide unrelated errors. Consider handling only relevant exceptions, and add logging or re-raise as needed to prevent silent failures.

logger.debug("Invalid settings, going to try another file:", exception)

self._settings = PydanticManager.load_from_file(self.settings_type, self.settings_file_path())
logger.debug("No valid settings found, using default settings")
self._settings = self.settings_type()
self.save()

def _clear_temp_files(self) -> None:
"""Clear temporary files"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from loguru import logger

from commonwealth.settings.bases.pykson_base import PyksonSettings
from commonwealth.settings.exceptions import SettingsFromTheFuture


class PyksonManager:
Expand Down Expand Up @@ -124,10 +123,12 @@ def get_settings_version_from_filename(filename: pathlib.Path) -> int:
self._settings = PyksonManager.load_from_file(self.settings_type, valid_file)
logger.debug(f"Using {valid_file} as settings source")
return
except SettingsFromTheFuture as exception:
except Exception as exception:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Broad exception handling could obscure root causes.

Consider catching only specific exceptions related to settings, or ensure unexpected exceptions are logged or re-raised to aid debugging.

logger.debug("Invalid settings, going to try another file:", exception)

self._settings = PyksonManager.load_from_file(self.settings_type, self.settings_file_path())
logger.debug("No valid settings found, using default settings")
self._settings = self.settings_type()
self.save()

def _clear_temp_files(self) -> None:
"""Clear temporary files"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,77 @@ def test_fallback_settings_save_load() -> None:
assert settings_manager.settings.version_2_variable == 2
assert settings_manager.settings.version_3_variable == 3
assert settings_manager.settings.version_12_variable == 12


def test_invalid_json_fallback_to_defaults_v1() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)

# Create a settings file with invalid JSON
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)
invalid_settings_file = settings_folder / "settings-1.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 1, "version_1_variable": 999, "invalid_json": }')

settings_manager = manager.Manager("ManagerTest", SettingsV1, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 1
assert settings_manager.settings.version_1_variable == 42

# Verify that a v1 settings will be replaced
settings_manager.save()
assert len(os.listdir(settings_folder)) == 1


def test_invalid_json_fallback_to_defaults_v1_from_invalid_v2() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)

# Create a valid JSON from settings V1
default_settings = SettingsV1()
default_settings.version_1_variable = 369
default_settings.save(settings_folder / "settings-1.json")

# Create a invalid JSON from settings V2
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 2, "version_2_variable": 999, "invalid_json": }')

settings_manager = manager.Manager("ManagerTest", SettingsV2, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 2
assert settings_manager.settings.version_1_variable == 369
assert settings_manager.settings.version_2_variable == 66

# Verify that a v2 settings will be replaced
settings_manager.save()
assert len(os.listdir(settings_folder)) == 2


def test_invalid_json_fallback_to_defaults_v2_from_invalid_v2_and_v1() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)

# Create a invalid JSON from settings V1
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 1, "version_1_variable": 999, "invalid_json": }')

# Create a invalid JSON from settings V2
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 2, "version_2_variable": 999, "invalid_json": }')

settings_manager = manager.Manager("ManagerTest", SettingsV2, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 2
assert settings_manager.settings.version_1_variable == 42
assert settings_manager.settings.version_2_variable == 66
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,77 @@ def test_fallback_settings_save_load() -> None:
assert settings_manager.settings.version_2_variable == 2
assert settings_manager.settings.version_3_variable == 3
assert settings_manager.settings.version_12_variable == 12


def test_invalid_json_fallback_to_defaults_v1() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)

# Create a settings file with invalid JSON
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)
invalid_settings_file = settings_folder / "settings-1.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 1, "version_1_variable": 999, "invalid_json": }')

settings_manager = PydanticManager("ManagerTest", SettingsV1, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 1
assert settings_manager.settings.version_1_variable == 42

# Verify that a v1 settings will be replaced
settings_manager.save()
assert len(os.listdir(settings_folder)) == 1


def test_invalid_json_fallback_to_defaults_v1_from_invalid_v2() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)

# Create a valid JSON from settings V1
default_settings = SettingsV1()
default_settings.version_1_variable = 369
default_settings.save(settings_folder / "settings-1.json")

# Create a invalid JSON from settings V2
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 2, "version_2_variable": 999, "invalid_json": }')

settings_manager = PydanticManager("ManagerTest", SettingsV2, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 2
assert settings_manager.settings.version_1_variable == 369
assert settings_manager.settings.version_2_variable == 66

# Verify that a v2 settings will be replaced
settings_manager.save()
assert len(os.listdir(settings_folder)) == 2


def test_invalid_json_fallback_to_defaults_v2_from_invalid_v2_and_v1() -> None:
temporary_folder = tempfile.mkdtemp()
config_path = pathlib.Path(temporary_folder)
settings_folder = config_path / "managertest"
settings_folder.mkdir(parents=True, exist_ok=True)

# Create a invalid JSON from settings V1
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 1, "version_1_variable": 999, "invalid_json": }')

# Create a invalid JSON from settings V2
invalid_settings_file = settings_folder / "settings-2.json"
with open(invalid_settings_file, "w", encoding="utf-8") as f:
f.write('{"VERSION": 2, "version_2_variable": 999, "invalid_json": }')

settings_manager = PydanticManager("ManagerTest", SettingsV2, config_path)

# Verify that the manager falls back to default values
assert settings_manager.settings.VERSION == 2
assert settings_manager.settings.version_1_variable == 42
assert settings_manager.settings.version_2_variable == 66