mirror of https://github.com/gmbrax/Pilgrim.git
				
				
				
			Merge pull request #54 from gmbrax/feat/use-a-toml-for-config
Feat/use a toml for config
This commit is contained in:
		
						commit
						26ef00fe3e
					
				|  | @ -20,6 +20,9 @@ | |||
|     dependencies = [ | ||||
|       "sqlalchemy", | ||||
|         "textual", | ||||
|         "tomli", | ||||
|         "tomli_w" | ||||
| 
 | ||||
| 
 | ||||
|     ] | ||||
|     [template.plugins.default] | ||||
|  |  | |||
|  | @ -1,19 +1,21 @@ | |||
| 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 ConfigManager | ||||
| 
 | ||||
| 
 | ||||
| class Application: | ||||
|     def __init__(self): | ||||
|         self.config_dir = DirectoryManager.get_config_directory() | ||||
|         self.database = Database() | ||||
|         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.ui = UIApp(session_manager, self.config_manager) | ||||
| 
 | ||||
|     def run(self): | ||||
|         print(f"URL do banco: {self.config_manager.database_url}") | ||||
|         self.database.create() | ||||
|         self.ui.run() | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,38 +5,24 @@ from pathlib import Path | |||
| import os | ||||
| import shutil | ||||
| 
 | ||||
| from pilgrim.utils import ConfigManager | ||||
| 
 | ||||
| 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, 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:///{db_path}", | ||||
|             f"sqlite:///{self.db_path}", | ||||
|             echo=False, | ||||
|             connect_args={"check_same_thread": False}, | ||||
|         ) | ||||
|  |  | |||
|  | @ -12,9 +12,9 @@ class NewDiaryModal(ModalScreen[str]): | |||
|         Binding("escape", "cancel", "Cancel"), | ||||
|         Binding("enter", "create_diary", "Create",priority=True), | ||||
|     ] | ||||
|     def __init__(self,autoopen=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: | ||||
|  |  | |||
|  | @ -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: | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| from .directory_manager import DirectoryManager | ||||
| from .config_manager import ConfigManager | ||||
| 
 | ||||
| __all__ = ['DirectoryManager'] | ||||
| __all__ = ['DirectoryManager', 'ConfigManager'] | ||||
|  |  | |||
|  | @ -0,0 +1,107 @@ | |||
| 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() | ||||
| 
 | ||||
|     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 | ||||
|         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) | ||||
| 
 | ||||
|             except tomli.TOMLDecodeError as 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"] | ||||
|             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): | ||||
|         # 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"{config_dir}/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"{config_dir}/config.toml", "wb") as f: | ||||
|                 tomli_w.dump(config, f) | ||||
|         except Exception as 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 | ||||
|         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 | ||||
| 
 | ||||
|     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 | ||||
|  | @ -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() | ||||
|         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(): | ||||
|                 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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue