From f3eed7486d6b39948d04e5fb7f65b1be4528bf42 Mon Sep 17 00:00:00 2001
From: WorldTeacher <41587052+WorldTeacher@users.noreply.github.com>
Date: Tue, 29 Oct 2024 16:07:30 +0100
Subject: [PATCH] feat: create config class to replace use of config file in
application
---
config.yaml | 62 -----------
config/__init__.py | 1 +
config/config.py | 167 ++++++++++++++++++++++++++++
src/__init__.py | 6 +-
src/backend/create_file.py | 2 -
src/backend/database.py | 11 +-
src/backend/delete_temp_contents.py | 6 +-
src/logic/thread_bookgrabber.py | 3 +-
src/logic/webrequest.py | 2 -
src/logic/zotero.py | 9 +-
src/ui/dialogs/settings.py | 56 +++++-----
src/ui/widgets/MessageCalendar.py | 2 +-
src/utils/icon.py | 8 +-
13 files changed, 224 insertions(+), 111 deletions(-)
delete mode 100644 config.yaml
create mode 100644 config/__init__.py
create mode 100644 config/config.py
diff --git a/config.yaml b/config.yaml
deleted file mode 100644
index d07083c..0000000
--- a/config.yaml
+++ /dev/null
@@ -1,62 +0,0 @@
-default_apps: true
-save_path: ~/Desktop/semap/db/temp/
-icon_path: icons/
-zotero:
- api_key:
- library_id: ""
- library_type: user
-
-custom_applications:
-- name: Text files
- extensions:
- - txt
- - md
- - rst
- application: Notepad
-- name: CSV files
- extensions:
- - csv
- application: Excel
-- name: pdf files
- extensions:
- - pdf
- application: Firefox
-- name: Word files
- extensions:
- - docx
- - doc
- application: Word
-- name: Excel files
- extensions:
- - xlsx
- - xls
- application: Excel
-database:
- name: test.sam
- path: ~\Desktop\semap\db\
- tempdir: ~\Desktop\semap\db\temp\
-mail:
- smtp_server: ''
- port: 0
- sender: ''
- user_name: ''
- use_user_name: false
- password: ''
- signature: '
-
-
-
-
'
diff --git a/config/__init__.py b/config/__init__.py
new file mode 100644
index 0000000..cca5d9b
--- /dev/null
+++ b/config/__init__.py
@@ -0,0 +1 @@
+from .config import Config
diff --git a/config/config.py b/config/config.py
new file mode 100644
index 0000000..c6e4c4e
--- /dev/null
+++ b/config/config.py
@@ -0,0 +1,167 @@
+from typing import Optional
+from dataclasses import dataclass
+from omegaconf import OmegaConf, DictConfig
+import os
+
+
+@dataclass
+class Zotero:
+ api_key: str
+ library_id: str
+ library_type: str
+
+ def getattr(self, name):
+ return getattr(self, name)
+
+ def _setattr(self, name, value):
+ setattr(self, name, value)
+
+
+@dataclass
+class Database:
+ name: str
+ path: str
+ tempdir: str
+
+ def getattr(self, name):
+ return getattr(self, name)
+
+ def _setattr(self, name, value):
+ setattr(self, name, value)
+
+
+@dataclass
+class Mail:
+ smtp_server: str
+ port: int
+ sender: str
+ password: str
+ use_user_name: bool
+ user_name: str
+ signature: str
+ empty_signature = """
+
+
+
+
"""
+
+ def getattr(self, name):
+ return getattr(self, name)
+
+ def _setattr(self, name, value):
+ setattr(self, name, value)
+
+
+class Config:
+ '''A class to handle the configuration of the application. After initializing, it will try to load the config file and store it for future access. Any changes made can be saved to the file using the .save() method. Changes are used in real time in the app, if a restart is required, the Application will show a window.
+
+ Raises:
+ RuntimeError: Configuration not loaded
+
+ KeyError: Invalid option
+
+ '''
+
+ _config: Optional[DictConfig] = None
+
+ def __init__(self, config_path: str):
+ """
+ Loads the configuration file and stores it for future access.
+
+ Args:
+ config_path (str): Path to the YAML configuration file.
+
+ Raises:
+ FileNotFoundError: Configuration file not found
+ """
+ if not os.path.exists(config_path):
+ raise FileNotFoundError(f"Configuration file not found: {config_path}")
+ self._config = OmegaConf.load(config_path)
+ self.config_path = config_path
+
+ def save(self):
+ """
+ Saves the current configuration to the file.
+
+ Args:
+ config_path (str): Path to the YAML configuration file.
+ """
+ OmegaConf.save(self._config, self.config_path)
+
+ @property
+ def zotero(self):
+ return Zotero(**self._config.zotero)
+
+ @property
+ def zotero_attr(self, name):
+ return getattr(self.zotero, name)
+
+ @zotero_attr.setter
+ def zotero_attr(self, name, value):
+ self.zotero._setattr(name, value)
+
+ @property
+ def database(self):
+ return Database(**self._config.database)
+
+ @property
+ def database_attr(self, name):
+ return getattr(self.database, name)
+
+ @database_attr.setter
+ def database_attr(self, name, value):
+ self.database._setattr(name, value)
+
+ @property
+ def mail(self):
+ return Mail(**self._config.mail)
+
+ def mail_attr(self, name):
+ return getattr(self.mail, name)
+
+ def set_mail_attr(self, name, value):
+ OmegaConf.update(self._config, f"mail.{name}", value)
+
+ def set_database_attr(self, name, value):
+ OmegaConf.update(self._config, f"database.{name}", value)
+
+ def set_zotero_attr(self, name, value):
+ OmegaConf.update(self._config, f"zotero.{name}", value)
+
+ @property
+ def default_apps(self):
+ return self._config.default_apps
+
+ @default_apps.setter
+ def default_apps(self, value: bool):
+ self._config.default_apps = value
+
+ @property
+ def save_path(self):
+ return self._config.save_path
+
+ @save_path.setter
+ def save_path(self, value: str):
+ self._config.save_path = value
+
+ @property
+ def icon_path(self):
+ """Path to Icon folder
+
+ Returns:
+ str: Folder path as string
+ """
+ return self._config.icon_path
diff --git a/src/__init__.py b/src/__init__.py
index ac7b067..eb61399 100644
--- a/src/__init__.py
+++ b/src/__init__.py
@@ -1,7 +1,11 @@
__version__ = "1.0.0"
__author__ = "Alexander Kirchner"
+from config import Config
+
+settings = Config("config/config.yaml")
+
+from .utils.icon import Icon
from .logic.log import MyLogger
-from .utils.icon import Icon
from .ui.userInterface import launch_gui as UI
diff --git a/src/backend/create_file.py b/src/backend/create_file.py
index 07a4a0a..b77f389 100644
--- a/src/backend/create_file.py
+++ b/src/backend/create_file.py
@@ -2,12 +2,10 @@ import os
from pathlib import Path
from icecream import ic
-from omegaconf import OmegaConf
from src.backend.database import Database
db = Database()
-config = OmegaConf.load("config.yaml")
def recreateFile(name, app_id, filetype, open=True) -> Path:
diff --git a/src/backend/database.py b/src/backend/database.py
index 3f000b9..403b1a1 100644
--- a/src/backend/database.py
+++ b/src/backend/database.py
@@ -3,6 +3,7 @@ import inspect
import sqlite3 as sql
import tempfile
from pathlib import Path
+from src import database
from typing import Any, Dict, List, Optional, Tuple, Union
# from icecream import ic
from omegaconf import OmegaConf
@@ -28,7 +29,7 @@ from src.utils import create_blob, dump_pickle, load_pickle
from .semester import generateSemesterByDate
from icecream import ic
-config = OmegaConf.load("config.yaml")
+
ascii_lowercase = "abcdefghijklmnopqrstuvwxyz0123456789)"
caller_frame = inspect.stack()[1]
# get the line that called the function
@@ -54,14 +55,14 @@ class Database:
self.name = script_name
self.logger = MyLogger(name)
if db_path is None:
- self.db_path = config.database.path + config.database.name
+ self.db_path = database.path + database.name
self.db_path = self.db_path.replace("~", str(Path.home()))
else:
self.db_path = db_path
self.checkDatabaseStatus()
def checkDatabaseStatus(self):
- path = config.database.path
+ path = database.path
path = path.replace("~", str(Path.home()))
# print(path)
path = os.path.abspath(path)
@@ -507,7 +508,7 @@ class Database:
str: The filename of the recreated file
"""
blob = self.getBlob(filename, app_id)
- tempdir = config.database.tempdir
+ tempdir = database.tempdir
tempdir = tempdir.replace("~", str(Path.home()))
tempdir_path = Path(tempdir)
if not os.path.exists(tempdir_path):
@@ -1414,7 +1415,7 @@ class Database:
"SELECT fileblob FROM elsa_files WHERE filename=?", (filename,), one=True
)[0]
# print(blob)
- tempdir = config.database.tempdir
+ tempdir = database.tempdir
tempdir = tempdir.replace("~", str(Path.home()))
tempdir_path = Path(tempdir)
if not os.path.exists(tempdir_path):
diff --git a/src/backend/delete_temp_contents.py b/src/backend/delete_temp_contents.py
index 6aacd95..c2c147d 100644
--- a/src/backend/delete_temp_contents.py
+++ b/src/backend/delete_temp_contents.py
@@ -1,16 +1,14 @@
import os
from pathlib import Path
+from src import database
-from omegaconf import OmegaConf
-
-config = OmegaConf.load("config.yaml")
def delete_temp_contents():
"""
delete_temp_contents deletes the contents of the temp directory.
"""
- path = config.database.tempdir
+ path = database.tempdir
path = path.replace("~", str(Path.home()))
path = Path(path)
path = path.resolve()
diff --git a/src/logic/thread_bookgrabber.py b/src/logic/thread_bookgrabber.py
index 1fcf55c..2853b05 100644
--- a/src/logic/thread_bookgrabber.py
+++ b/src/logic/thread_bookgrabber.py
@@ -2,12 +2,11 @@ import sqlite3
from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal
-from omegaconf import OmegaConf
from src.backend.database import Database
from src.logic.log import MyLogger
from src.logic.webrequest import BibTextTransformer, WebRequest
-config = OmegaConf.load("config.yaml")
+
class BookGrabber(QThread):
diff --git a/src/logic/webrequest.py b/src/logic/webrequest.py
index ee04a99..dbef829 100644
--- a/src/logic/webrequest.py
+++ b/src/logic/webrequest.py
@@ -1,6 +1,5 @@
import requests
from bs4 import BeautifulSoup
-from omegaconf import OmegaConf
# import sleep_and_retry decorator to retry requests
from ratelimit import limits, sleep_and_retry
@@ -10,7 +9,6 @@ from src.logic.log import MyLogger
from src.transformers import ARRAYData, BibTeXData, COinSData, RDSData, RISData
logger = MyLogger(__name__)
-config = OmegaConf.load("config.yaml")
API_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndexrecord/{}/"
PPN_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndex/Search?type0%5B%5D=allfields&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=au&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ti&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ct&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=isn&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ta&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=co&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=py&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pp&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pu&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=si&lookfor0%5B%5D={}&join=AND&bool0%5B%5D=AND&type0%5B%5D=zr&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=cc&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND"
diff --git a/src/logic/zotero.py b/src/logic/zotero.py
index 3ad9679..33173b5 100644
--- a/src/logic/zotero.py
+++ b/src/logic/zotero.py
@@ -1,10 +1,8 @@
from pyzotero import zotero
from dataclasses import dataclass
from src.logic.webrequest import WebRequest, BibTextTransformer
-from omegaconf import OmegaConf
+from src import settings
-config = OmegaConf.load("config.yaml")
-config = config["zotero"]
@dataclass
@@ -160,9 +158,12 @@ class JournalArticle:
class ZoteroController:
+ zoterocfg = settings.zotero
def __init__(self):
self.zot = zotero.Zotero(
- config["library_id"], config["library_type"], config["api_key"]
+ self.zoterocfg.library_id,
+ self.zoterocfg.library_type,
+ self.zoterocfg.api_key,
)
def get_books(self):
diff --git a/src/ui/dialogs/settings.py b/src/ui/dialogs/settings.py
index 6f62797..c77be0e 100644
--- a/src/ui/dialogs/settings.py
+++ b/src/ui/dialogs/settings.py
@@ -1,11 +1,9 @@
-from omegaconf import OmegaConf
from PyQt6 import QtCore, QtGui, QtWidgets
-from src import Icon
+from src import Icon, settings
from .dialog_sources.Ui_settings import Ui_Dialog as _settings
-config = OmegaConf.load("config.yaml")
base = """'