From 3843be6e1302bb03bddc36197e4684ab5b333ed4 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 02:55:52 -0300 Subject: [PATCH 1/8] Add the tomli library and create the config_manager.py to manage the configuration file and also add the dependency injection on the ui.py via the Application class --- pyproject.toml | 2 ++ src/pilgrim/application.py | 5 +++-- src/pilgrim/ui/ui.py | 4 +++- src/pilgrim/utils/__init__.py | 3 ++- src/pilgrim/utils/config_manager.py | 35 +++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 src/pilgrim/utils/config_manager.py diff --git a/pyproject.toml b/pyproject.toml index eb7ec6b..4ccb712 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,8 @@ dependencies = [ "sqlalchemy", "textual", + "tomli", + ] [template.plugins.default] diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index 380c4c2..e7b5419 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -1,17 +1,18 @@ from pilgrim.database import Database from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.ui import UIApp -from pilgrim.utils import DirectoryManager +from pilgrim.utils import DirectoryManager, ConfigManager class Application: def __init__(self): self.config_dir = DirectoryManager.get_config_directory() self.database = Database() + self.config_manager = ConfigManager() session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) - self.ui = UIApp(session_manager) + self.ui = UIApp(session_manager,self.config_manager) def run(self): self.database.create() diff --git a/src/pilgrim/ui/ui.py b/src/pilgrim/ui/ui.py index 2443f74..5557993 100644 --- a/src/pilgrim/ui/ui.py +++ b/src/pilgrim/ui/ui.py @@ -9,6 +9,7 @@ from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.screens.about_screen import AboutScreen from pilgrim.ui.screens.diary_list_screen import DiaryListScreen from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen +from pilgrim.utils import ConfigManager CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" @@ -16,9 +17,10 @@ CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" class UIApp(App): CSS_PATH = CSS_FILE_PATH - def __init__(self,service_manager: ServiceManager, **kwargs): + def __init__(self,service_manager: ServiceManager, config_manager: ConfigManager, **kwargs): super().__init__(**kwargs) self.service_manager = service_manager + self.config_manager = config_manager def on_mount(self) -> None: diff --git a/src/pilgrim/utils/__init__.py b/src/pilgrim/utils/__init__.py index f419fe1..b9fbd1b 100644 --- a/src/pilgrim/utils/__init__.py +++ b/src/pilgrim/utils/__init__.py @@ -1,3 +1,4 @@ from .directory_manager import DirectoryManager +from .config_manager import ConfigManager -__all__ = ['DirectoryManager'] +__all__ = ['DirectoryManager', 'ConfigManager'] diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py new file mode 100644 index 0000000..05b821f --- /dev/null +++ b/src/pilgrim/utils/config_manager.py @@ -0,0 +1,35 @@ +from threading import Lock + +import tomli +from pilgrim.utils import DirectoryManager + +class SingletonMeta(type): + _instances = {} + _lock: Lock = Lock() + + def __call__(cls, *args, **kwargs): + with cls._lock: + if cls not in cls._instances: + instance = super().__call__(*args, **kwargs) + cls._instances[cls] = instance + return cls._instances[cls] + +class ConfigManager(metaclass=SingletonMeta): + def __init__(self): + self.database_url = None + self.database_type = None + self.auto_open_diary = None + self.auto_open_new_diary = None + @staticmethod + def read_config(): + try: + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: + data = tomli.load(f) + print(data) + except FileNotFoundError: + print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: + print(f"Error decoding TOML: {e}") + + def set_database_url(self): + pass \ No newline at end of file From fe35cb93bdae42f7e4626586b1733b97fdd82feb Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 15:30:47 -0300 Subject: [PATCH 2/8] Move get_database_path from database.py to directory_manager.py --- src/pilgrim/database.py | 30 ++++---------------------- src/pilgrim/utils/directory_manager.py | 24 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index aba4219..5f8bd97 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -5,36 +5,14 @@ from pathlib import Path import os import shutil + Base = declarative_base() -def get_database_path() -> Path: - """ - Get the database file path following XDG Base Directory specification. - Creates the directory if it doesn't exist. - """ - # Get home directory - home = Path.home() - - # Create .pilgrim directory if it doesn't exist - pilgrim_dir = home / ".pilgrim" - pilgrim_dir.mkdir(exist_ok=True) - - # Database file path - db_path = pilgrim_dir / "database.db" - - # If database doesn't exist in new location but exists in current directory, - # migrate it - if not db_path.exists(): - current_db = Path("database.db") - if current_db.exists(): - shutil.copy2(current_db, db_path) - print(f"Database migrated from {current_db} to {db_path}") - - return db_path + class Database: - def __init__(self): - db_path = get_database_path() + def __init__(self,): + db_path = "./" self.engine = create_engine( f"sqlite:///{db_path}", echo=False, diff --git a/src/pilgrim/utils/directory_manager.py b/src/pilgrim/utils/directory_manager.py index c6a0708..a03601a 100644 --- a/src/pilgrim/utils/directory_manager.py +++ b/src/pilgrim/utils/directory_manager.py @@ -1,4 +1,5 @@ import os +import shutil from pathlib import Path @@ -37,3 +38,26 @@ class DirectoryManager: def get_diary_images_directory(directory_name: str) -> Path: """Returns the images directory path for a specific diary.""" return DirectoryManager.get_diary_data_directory(directory_name) / "images" + + @staticmethod + def get_database_path() -> Path: + """ + Get the database file path following XDG Base Directory specification. + Creates the directory if it doesn't exist. + """ + + pilgrim_dir = DirectoryManager.get_config_directory() + pilgrim_dir.mkdir(exist_ok=True) + + # Database file path + db_path = pilgrim_dir / "database.db" + + # If database doesn't exist in new location but exists in current directory, + # migrate it + if not db_path.exists(): + current_db = Path("database.db") + if current_db.exists(): + shutil.copy2(current_db, db_path) + print(f"Database migrated from {current_db} to {db_path}") + + return db_path From a540347127818bced8931703b138a37486e6a3e1 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 15:31:19 -0300 Subject: [PATCH 3/8] Add Tomli_w library to pyproject.toml --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 4ccb712..0a1b086 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ "sqlalchemy", "textual", "tomli", + "tomli_w" ] From bdaa37e355330a67f131c0a83f8279a9481fb3f4 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 16:01:34 -0300 Subject: [PATCH 4/8] Add the database file path now is read by the configuration file --- src/pilgrim/application.py | 6 +-- src/pilgrim/database.py | 7 +-- src/pilgrim/utils/config_manager.py | 79 +++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index e7b5419..7ab3acf 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -1,20 +1,20 @@ from pilgrim.database import Database from pilgrim.service.servicemanager import ServiceManager from pilgrim.ui.ui import UIApp -from pilgrim.utils import DirectoryManager, ConfigManager +from pilgrim.utils import ConfigManager class Application: def __init__(self): - self.config_dir = DirectoryManager.get_config_directory() - self.database = Database() self.config_manager = ConfigManager() + self.database = Database(self.config_manager) session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) self.ui = UIApp(session_manager,self.config_manager) def run(self): + self.config_manager.read_config() self.database.create() self.ui.run() diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index 5f8bd97..fd144a0 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -5,16 +5,17 @@ from pathlib import Path import os import shutil +from pilgrim.utils import ConfigManager Base = declarative_base() class Database: - def __init__(self,): - db_path = "./" + def __init__(self,config_manager:ConfigManager): + db_path = config_manager.database_url self.engine = create_engine( - f"sqlite:///{db_path}", + f"sqlite:///{config_manager.database_url}", echo=False, connect_args={"check_same_thread": False}, ) diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 05b821f..66d643c 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -1,8 +1,13 @@ +import os.path +from os import PathLike from threading import Lock import tomli +import tomli_w + from pilgrim.utils import DirectoryManager + class SingletonMeta(type): _instances = {} _lock: Lock = Lock() @@ -14,22 +19,78 @@ class SingletonMeta(type): cls._instances[cls] = instance return cls._instances[cls] + class ConfigManager(metaclass=SingletonMeta): def __init__(self): self.database_url = None self.database_type = None self.auto_open_diary = None self.auto_open_new_diary = None - @staticmethod - def read_config(): + self.config_dir = DirectoryManager.get_config_directory() + self.__data = None + + def read_config(self): + if os.path.exists(f"{DirectoryManager.get_config_directory()}/config.toml"): + try: + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: + data = tomli.load(f) + print(data) + except FileNotFoundError: + print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: + print(f"Error decoding TOML: {e}") + + self.__data = data + self.database_url = self.__data["database"]["url"] + self.database_type = self.__data["database"]["type"] + + if self.__data["settings"]["diary"]["auto_open_diary_on_startup"] == "": + self.auto_open_diary = None + self.auto_open_new_diary = self.__data["settings"]["diary"]["auto_open_on_creation"] + else: + print("Error: config.toml not found.") + self.create_config() + self.read_config() + + def create_config(self, config: dict = None): + default = { + "database": { + "url": f"{DirectoryManager.get_config_directory()}/database.db", + "type": "sqlite" + }, + "settings": { + "diary": { + "auto_open_diary_on_startup": "", + "auto_open_on_creation": False + } + } + } + if config is None: + config = default try: - with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: - data = tomli.load(f) - print(data) + with open(f"{DirectoryManager.get_config_directory()}/config.toml", "wb") as f: + tomli_w.dump(config, f) except FileNotFoundError: print("Error: config.toml not found.") - except tomli.TOMLDecodeError as e: - print(f"Error decoding TOML: {e}") - def set_database_url(self): - pass \ No newline at end of file + def save_config(self): + if self.__data is None: + self.read_config() + self.__data["database"]["url"] = self.database_url + self.__data["database"]["type"] = self.database_type + self.__data["settings"]["diary"]["auto_open_diary_on_startup"] = self.auto_open_diary or "" + self.__data["settings"]["diary"]["auto_open_on_creation"] = self.auto_open_new_diary + + self.create_config(self.__data) + + def set_config_dir(self, value): + self.config_dir = value + + def set_database_url(self, value: str): + self.database_url = value + + def set_auto_open_diary(self, value: str): + self.auto_open_diary = value + + def set_auto_open_new_diary(self, value: bool): + self.auto_open_new_diary = value From 967c7e4ce64587b42764632c4a2bb46bb58118b6 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 16:39:31 -0300 Subject: [PATCH 5/8] Fix the Database no being put on the right path according with the config.toml --- src/pilgrim/application.py | 5 +++-- src/pilgrim/database.py | 13 ++++++++++--- src/pilgrim/ui/screens/new_diary_modal.py | 2 +- src/pilgrim/utils/config_manager.py | 14 ++++++++++---- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/pilgrim/application.py b/src/pilgrim/application.py index 7ab3acf..1d2f11a 100644 --- a/src/pilgrim/application.py +++ b/src/pilgrim/application.py @@ -7,14 +7,15 @@ from pilgrim.utils import ConfigManager class Application: def __init__(self): self.config_manager = ConfigManager() + self.config_manager.read_config() # Chamar antes de criar o Database self.database = Database(self.config_manager) session = self.database.session() session_manager = ServiceManager() session_manager.set_session(session) - self.ui = UIApp(session_manager,self.config_manager) + self.ui = UIApp(session_manager, self.config_manager) def run(self): - self.config_manager.read_config() + print(f"URL do banco: {self.config_manager.database_url}") self.database.create() self.ui.run() diff --git a/src/pilgrim/database.py b/src/pilgrim/database.py index fd144a0..8d472af 100644 --- a/src/pilgrim/database.py +++ b/src/pilgrim/database.py @@ -12,10 +12,17 @@ Base = declarative_base() class Database: - def __init__(self,config_manager:ConfigManager): - db_path = config_manager.database_url + + def __init__(self, config_manager: ConfigManager): + self.db_path = config_manager.database_url + + # Garantir que o diretório existe + db_dir = os.path.dirname(self.db_path) + if not os.path.exists(db_dir): + os.makedirs(db_dir, exist_ok=True) + self.engine = create_engine( - f"sqlite:///{config_manager.database_url}", + f"sqlite:///{self.db_path}", echo=False, connect_args={"check_same_thread": False}, ) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index e91f516..ecf25bc 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -12,7 +12,7 @@ class NewDiaryModal(ModalScreen[str]): Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self,autoopen=True): + def __init__(self,autoopen:bool = True): super().__init__() self.auto_open = autoopen self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 66d643c..59c1faf 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -53,9 +53,14 @@ class ConfigManager(metaclass=SingletonMeta): self.read_config() def create_config(self, config: dict = None): + # Garantir que o diretório de configuração existe + config_dir = DirectoryManager.get_config_directory() + if not os.path.exists(config_dir): + os.makedirs(config_dir, exist_ok=True) + default = { "database": { - "url": f"{DirectoryManager.get_config_directory()}/database.db", + "url": f"{config_dir}/database.db", "type": "sqlite" }, "settings": { @@ -67,11 +72,12 @@ class ConfigManager(metaclass=SingletonMeta): } if config is None: config = default + try: - with open(f"{DirectoryManager.get_config_directory()}/config.toml", "wb") as f: + with open(f"{config_dir}/config.toml", "wb") as f: tomli_w.dump(config, f) - except FileNotFoundError: - print("Error: config.toml not found.") + except Exception as e: + print(f"Erro ao criar config: {e}") def save_config(self): if self.__data is None: From a13c56a3a3f9a35644a7e8a7cb7cb17d3be25dda Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 17:24:45 -0300 Subject: [PATCH 6/8] Fix the NewDiaryModal not accessing the toml file properly to set the auto_open flag --- src/pilgrim/ui/screens/new_diary_modal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pilgrim/ui/screens/new_diary_modal.py b/src/pilgrim/ui/screens/new_diary_modal.py index ecf25bc..0e713a5 100644 --- a/src/pilgrim/ui/screens/new_diary_modal.py +++ b/src/pilgrim/ui/screens/new_diary_modal.py @@ -12,9 +12,9 @@ class NewDiaryModal(ModalScreen[str]): Binding("escape", "cancel", "Cancel"), Binding("enter", "create_diary", "Create",priority=True), ] - def __init__(self,autoopen:bool = True): + def __init__(self): super().__init__() - self.auto_open = autoopen + self.auto_open = self.app.config_manager.auto_open_new_diary self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input def compose(self) -> ComposeResult: From 4436d5e081e4c300f745372336cc46ba118ae712 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Miranda Date: Wed, 16 Jul 2025 18:12:32 -0300 Subject: [PATCH 7/8] Update src/pilgrim/utils/directory_manager.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/pilgrim/utils/directory_manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pilgrim/utils/directory_manager.py b/src/pilgrim/utils/directory_manager.py index a03601a..7a39670 100644 --- a/src/pilgrim/utils/directory_manager.py +++ b/src/pilgrim/utils/directory_manager.py @@ -45,11 +45,7 @@ class DirectoryManager: Get the database file path following XDG Base Directory specification. Creates the directory if it doesn't exist. """ - pilgrim_dir = DirectoryManager.get_config_directory() - pilgrim_dir.mkdir(exist_ok=True) - - # Database file path db_path = pilgrim_dir / "database.db" # If database doesn't exist in new location but exists in current directory, @@ -57,7 +53,11 @@ class DirectoryManager: if not db_path.exists(): current_db = Path("database.db") if current_db.exists(): - shutil.copy2(current_db, db_path) - print(f"Database migrated from {current_db} to {db_path}") + try: + shutil.copy2(current_db, db_path) + # Consider using logging instead of print + print(f"Database migrated from {current_db} to {db_path}") + except (OSError, shutil.Error) as e: + raise RuntimeError(f"Failed to migrate database: {e}") return db_path From 23ef60b55a649de3f33ed93efb8906e3e47a9dc6 Mon Sep 17 00:00:00 2001 From: Gustavo Henrique Santos Souza de Miranda Date: Wed, 16 Jul 2025 18:28:42 -0300 Subject: [PATCH 8/8] Improve exception handling, remove debug print statements --- src/pilgrim/utils/config_manager.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/pilgrim/utils/config_manager.py b/src/pilgrim/utils/config_manager.py index 59c1faf..7a0f856 100644 --- a/src/pilgrim/utils/config_manager.py +++ b/src/pilgrim/utils/config_manager.py @@ -34,11 +34,11 @@ class ConfigManager(metaclass=SingletonMeta): try: with open(f"{DirectoryManager.get_config_directory()}/config.toml", "rb") as f: data = tomli.load(f) - print(data) - except FileNotFoundError: - print("Error: config.toml not found.") + except tomli.TOMLDecodeError as e: - print(f"Error decoding TOML: {e}") + raise ValueError(f"Invalid TOML configuration: {e}") + except Exception as e: + raise RuntimeError(f"Error reading configuration: {e}") self.__data = data self.database_url = self.__data["database"]["url"] @@ -77,17 +77,22 @@ class ConfigManager(metaclass=SingletonMeta): with open(f"{config_dir}/config.toml", "wb") as f: tomli_w.dump(config, f) except Exception as e: - print(f"Erro ao criar config: {e}") + raise RuntimeError(f"Error creating configuration: {e}") def save_config(self): if self.__data is None: self.read_config() + if self.__data is None: + raise RuntimeError("Error reading configuration.") + self.__data["database"]["url"] = self.database_url self.__data["database"]["type"] = self.database_type self.__data["settings"]["diary"]["auto_open_diary_on_startup"] = self.auto_open_diary or "" self.__data["settings"]["diary"]["auto_open_on_creation"] = self.auto_open_new_diary - - self.create_config(self.__data) + try: + self.create_config(self.__data) + except Exception as e: + raise RuntimeError(f"Error saving configuration: {e}") def set_config_dir(self, value): self.config_dir = value