Compare commits

...
Author SHA1 Message Date
Gustavo Henrique Miranda 9d259d2119 Merge a59af26c9d into 8f36e5a770 2025-07-17 01:50:33 +00:00
Gustavo Henrique Miranda a59af26c9d Merge pull request #55 from gmbrax/feat/use-a-toml-for-config
Feat/use a toml for config
2025-07-16 22:50:30 -03:00
Gustavo Henrique Santos Souza de Miranda 23ef60b55a Improve exception handling, remove debug print statements 2025-07-16 18:28:42 -03:00
Gustavo Henrique Mirandaandcoderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> 4436d5e081 Update src/pilgrim/utils/directory_manager.py
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-07-16 18:12:32 -03:00
Gustavo Henrique Santos Souza de Miranda a13c56a3a3 Fix the NewDiaryModal not accessing the toml file properly to set the auto_open flag 2025-07-16 17:24:45 -03:00
Gustavo Henrique Santos Souza de Miranda 967c7e4ce6 Fix the Database no being put on the right path according with the config.toml 2025-07-16 16:39:31 -03:00
Gustavo Henrique Santos Souza de Miranda bdaa37e355 Add the database file path now is read by the configuration file 2025-07-16 16:01:34 -03:00
Gustavo Henrique Santos Souza de Miranda a540347127 Add Tomli_w library to pyproject.toml 2025-07-16 15:31:19 -03:00
Gustavo Henrique Santos Souza de Miranda fe35cb93bd Move get_database_path from database.py to directory_manager.py 2025-07-16 15:30:47 -03:00
Gustavo Henrique Santos Souza de Miranda 3843be6e13 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 2025-07-16 02:55:52 -03:00
Gustavo Henrique Miranda 0adb230dd7 Merge pull request #52 from gmbrax/fix/move-create-diary-to-modal
Change to call the method in the super class on the _on_screen_resume  method
2025-07-16 01:30:35 -03:00
Gustavo Henrique Santos Souza de Miranda 167c2d8928 Change to call the method in the super class on the _on_screen_resume method 2025-07-16 00:50:07 -03:00
Gustavo Henrique Miranda 5b0f894c88 Merge pull request #50 from gmbrax/fix/bump-version
Bump the version to 0.0.4 on about_screen.py and pyproject.toml
2025-07-16 00:42:42 -03:00
Gustavo Henrique Santos Souza de Miranda 2b851fc7c7 Add the use of importlib.metadata.version to keep the version string in sync with the pyproject.toml 2025-07-16 00:39:28 -03:00
Gustavo Henrique Santos Souza de Miranda a3123fe322 Bump the version to 0.0.4 on about_screen.py and pyproject.toml 2025-07-16 00:25:37 -03:00
Gustavo Henrique Miranda 8f36e5a770 Merge pull request #37 from gmbrax/dependabot/pip/typing-extensions-4.14.1
Bump typing-extensions from 4.14.0 to 4.14.1
2025-07-14 19:15:54 -03:00
Gustavo Henrique Miranda 11e9cf6e75 Merge pull request #38 from gmbrax/dependabot/pip/textual-approx-eq-4.0.0
Update textual requirement from ~=3.3.0 to ~=4.0.0
2025-07-14 19:14:47 -03:00
10 changed files with 164 additions and 38 deletions
+4 -1
View File
@@ -5,7 +5,7 @@
[project] [project]
name = "Pilgrim" name = "Pilgrim"
version = "0.0.3" version = "0.0.4"
authors = [ authors = [
{ name="Gustavo Henrique Santos Souza de Miranda", email="gustavohssmiranda@gmail.com" } { name="Gustavo Henrique Santos Souza de Miranda", email="gustavohssmiranda@gmail.com" }
] ]
@@ -20,6 +20,9 @@
dependencies = [ dependencies = [
"sqlalchemy", "sqlalchemy",
"textual", "textual",
"tomli",
"tomli_w"
] ]
[template.plugins.default] [template.plugins.default]
+6 -4
View File
@@ -1,19 +1,21 @@
from pilgrim.database import Database from pilgrim.database import Database
from pilgrim.service.servicemanager import ServiceManager from pilgrim.service.servicemanager import ServiceManager
from pilgrim.ui.ui import UIApp from pilgrim.ui.ui import UIApp
from pilgrim.utils import DirectoryManager from pilgrim.utils import ConfigManager
class Application: class Application:
def __init__(self): def __init__(self):
self.config_dir = DirectoryManager.get_config_directory() self.config_manager = ConfigManager()
self.database = Database() self.config_manager.read_config() # Chamar antes de criar o Database
self.database = Database(self.config_manager)
session = self.database.session() session = self.database.session()
session_manager = ServiceManager() session_manager = ServiceManager()
session_manager.set_session(session) session_manager.set_session(session)
self.ui = UIApp(session_manager) self.ui = UIApp(session_manager, self.config_manager)
def run(self): def run(self):
print(f"URL do banco: {self.config_manager.database_url}")
self.database.create() self.database.create()
self.ui.run() self.ui.run()
+13 -27
View File
@@ -5,38 +5,24 @@ from pathlib import Path
import os import os
import shutil import shutil
from pilgrim.utils import ConfigManager
Base = declarative_base() 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: 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( self.engine = create_engine(
f"sqlite:///{db_path}", f"sqlite:///{self.db_path}",
echo=False, echo=False,
connect_args={"check_same_thread": False}, connect_args={"check_same_thread": False},
) )
+2 -2
View File
@@ -3,7 +3,7 @@ from textual.binding import Binding
from textual.screen import Screen from textual.screen import Screen
from textual.widgets import Header, Footer, Button, Label, TextArea from textual.widgets import Header, Footer, Button, Label, TextArea
from textual.containers import Container from textual.containers import Container
from importlib.metadata import version
class AboutScreen(Screen[bool]): class AboutScreen(Screen[bool]):
"""Screen to display application information.""" """Screen to display application information."""
@@ -20,7 +20,7 @@ class AboutScreen(Screen[bool]):
self.app_title = Label("Pilgrim", id="AboutScreen_AboutTitle",classes="AboutScreen_AboutTitle") self.app_title = Label("Pilgrim", id="AboutScreen_AboutTitle",classes="AboutScreen_AboutTitle")
self.content = Label("A TUI Based Travel Diary Application", id="AboutScreen_AboutContent", self.content = Label("A TUI Based Travel Diary Application", id="AboutScreen_AboutContent",
classes="AboutScreen_AboutContent") classes="AboutScreen_AboutContent")
self.version = Label("Version: 0.0.1", id="AboutScreen_AboutVersion", self.version = Label(f"Version: {version('Pilgrim')}", id="AboutScreen_AboutVersion",
classes="AboutScreen_AboutVersion") classes="AboutScreen_AboutVersion")
self.developer = Label("Developed By: Gustavo Henrique Miranda ", id="AboutScreen_AboutAuthor") self.developer = Label("Developed By: Gustavo Henrique Miranda ", id="AboutScreen_AboutAuthor")
self.contact = Label("git.gustavomiranda.xyz", id="AboutScreen_AboutContact", self.contact = Label("git.gustavomiranda.xyz", id="AboutScreen_AboutContact",
@@ -216,6 +216,7 @@ class DiaryListScreen(Screen):
self.notify(f"Creation canceled...") self.notify(f"Creation canceled...")
def _on_screen_resume(self) -> None: def _on_screen_resume(self) -> None:
super()._on_screen_resume()
self.refresh_diaries() self.refresh_diaries()
def action_edit_selected_diary(self): def action_edit_selected_diary(self):
+2 -2
View File
@@ -12,9 +12,9 @@ class NewDiaryModal(ModalScreen[str]):
Binding("escape", "cancel", "Cancel"), Binding("escape", "cancel", "Cancel"),
Binding("enter", "create_diary", "Create",priority=True), Binding("enter", "create_diary", "Create",priority=True),
] ]
def __init__(self,autoopen=True): def __init__(self):
super().__init__() 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 self.name_input = Input(id="NewDiaryModal-NameInput",classes="NewDiaryModal-NameInput") # This ID is fine, it's specific to the input
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
+3 -1
View File
@@ -9,6 +9,7 @@ from pilgrim.service.servicemanager import ServiceManager
from pilgrim.ui.screens.about_screen import AboutScreen from pilgrim.ui.screens.about_screen import AboutScreen
from pilgrim.ui.screens.diary_list_screen import DiaryListScreen from pilgrim.ui.screens.diary_list_screen import DiaryListScreen
from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen from pilgrim.ui.screens.edit_entry_screen import EditEntryScreen
from pilgrim.utils import ConfigManager
CSS_FILE_PATH = Path(__file__).parent / "styles" / "pilgrim.css" 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): class UIApp(App):
CSS_PATH = CSS_FILE_PATH 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) super().__init__(**kwargs)
self.service_manager = service_manager self.service_manager = service_manager
self.config_manager = config_manager
def on_mount(self) -> None: def on_mount(self) -> None:
+2 -1
View File
@@ -1,3 +1,4 @@
from .directory_manager import DirectoryManager from .directory_manager import DirectoryManager
from .config_manager import ConfigManager
__all__ = ['DirectoryManager'] __all__ = ['DirectoryManager', 'ConfigManager']
+107
View File
@@ -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
+24
View File
@@ -1,4 +1,5 @@
import os import os
import shutil
from pathlib import Path from pathlib import Path
@@ -37,3 +38,26 @@ class DirectoryManager:
def get_diary_images_directory(directory_name: str) -> Path: def get_diary_images_directory(directory_name: str) -> Path:
"""Returns the images directory path for a specific diary.""" """Returns the images directory path for a specific diary."""
return DirectoryManager.get_diary_data_directory(directory_name) / "images" 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