From e7e2f20b70e74be35e146ec6ac76416335aacad4 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 9 Jan 2025 11:50:34 +0000 Subject: [PATCH 1/3] :sparkles: Add a context manager for updating/saving the configuration --- src/braindrop/app/data/config.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/braindrop/app/data/config.py b/src/braindrop/app/data/config.py index a14c238..820945e 100644 --- a/src/braindrop/app/data/config.py +++ b/src/braindrop/app/data/config.py @@ -2,10 +2,12 @@ ############################################################################## # Python imports. +from contextlib import contextmanager from dataclasses import asdict, dataclass from functools import lru_cache from json import dumps, loads from pathlib import Path +from typing import Iterator ############################################################################## # Local imports. @@ -81,4 +83,25 @@ def load_configuration() -> Configuration: ) +############################################################################## +@contextmanager +def update_configuration() -> Iterator[Configuration]: + """Context manager for updating the configuration. + + Loads the configuration and makes it available, then ensures it is + saved. + + Example: + ```python + with update_configuration() as config: + config.meaning = 42 + ``` + """ + configuration = load_configuration() + try: + yield configuration + finally: + save_configuration(configuration) + + ### config.py ends here From 974ffaf0c5a5c0533ce0d38786b0aa1072171ba1 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 9 Jan 2025 11:51:03 +0000 Subject: [PATCH 2/3] :zap: Export the context manager --- src/braindrop/app/data/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/braindrop/app/data/__init__.py b/src/braindrop/app/data/__init__.py index 2944b77..c910e65 100644 --- a/src/braindrop/app/data/__init__.py +++ b/src/braindrop/app/data/__init__.py @@ -2,7 +2,12 @@ ############################################################################## # Local imports. -from .config import configuration_file, load_configuration, save_configuration +from .config import ( + configuration_file, + load_configuration, + save_configuration, + update_configuration, +) from .exit_state import ExitState from .local import LocalData, Raindrops, local_data_file from .token import token_file @@ -18,6 +23,7 @@ "Raindrops", "save_configuration", "token_file", + "update_configuration", ] From f4dcd04a6c37120b12c81a32e25b25ec4367387e Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 9 Jan 2025 11:51:19 +0000 Subject: [PATCH 3/3] :hammer: Switch config updates to use update_configuration --- src/braindrop/app/braindrop.py | 13 +++++++++---- src/braindrop/app/screens/main.py | 16 +++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/braindrop/app/braindrop.py b/src/braindrop/app/braindrop.py index a72b43d..e7668a1 100644 --- a/src/braindrop/app/braindrop.py +++ b/src/braindrop/app/braindrop.py @@ -12,7 +12,13 @@ ############################################################################## # Local imports. from ..raindrop import API -from .data import ExitState, load_configuration, save_configuration, token_file +from .data import ( + ExitState, + load_configuration, + save_configuration, + token_file, + update_configuration, +) from .screens import Main, TokenInput @@ -71,9 +77,8 @@ def __init__(self) -> None: def watch_theme(self) -> None: """Save the application's theme when it's changed.""" - configuration = load_configuration() - configuration.theme = self.theme - save_configuration(configuration) + with update_configuration() as config: + config.theme = self.theme @staticmethod def environmental_token() -> str | None: diff --git a/src/braindrop/app/screens/main.py b/src/braindrop/app/screens/main.py index c22df84..846199a 100644 --- a/src/braindrop/app/screens/main.py +++ b/src/braindrop/app/screens/main.py @@ -62,6 +62,7 @@ local_data_file, save_configuration, token_file, + update_configuration, ) from ..messages import ShowCollection, ShowTagged from ..providers import CollectionCommands, CommandsProvider, MainCommands, TagCommands @@ -379,9 +380,8 @@ def action_tag_order_command(self) -> None: self.query_one(Navigation).tags_by_count = ( by_count := not self.query_one(Navigation).tags_by_count ) - config = load_configuration() - config.show_tags_by_count = by_count - save_configuration(config) + with update_configuration() as config: + config.show_tags_by_count = by_count @on(ShowAll) def action_show_all_command(self) -> None: @@ -426,9 +426,8 @@ def action_escape_command(self) -> None: def action_details_command(self) -> None: """Toggle the details of the raindrop details view.""" self.toggle_class("details-hidden") - config = load_configuration() - config.details_visible = not self.has_class("details-hidden") - save_configuration(config) + with update_configuration() as config: + config.details_visible = not self.has_class("details-hidden") @on(CompactMode) def action_compact_mode_command(self) -> None: @@ -436,9 +435,8 @@ def action_compact_mode_command(self) -> None: self.query_one(RaindropsView).compact = not self.query_one( RaindropsView ).compact - config = load_configuration() - config.compact_mode = self.query_one(RaindropsView).compact - save_configuration(config) + with update_configuration() as config: + config.compact_mode = self.query_one(RaindropsView).compact @on(Search) @work