Spaces:
Sleeping
Sleeping
"""Configuration management for fabric-to-espanso.""" | |
# TODO: check if config.validate wel gebruikt wordt | |
from typing import Dict, Any, Optional | |
from dataclasses import dataclass, field | |
from urllib.parse import urlparse | |
from pathlib import Path | |
import logging | |
from parameters import ( | |
FABRIC_PATTERNS_FOLDER, | |
YAML_OUTPUT_FOLDER, | |
DEFAULT_TRIGGER, | |
OBSIDIAN_OUTPUT_FOLDER, | |
OBSIDIAN_INPUT_FOLDER, | |
BASE_WORDS, | |
QDRANT_URL, | |
USE_FASTEMBED, | |
EMBED_MODEL_DENSE, | |
EMBED_MODEL_SPARSE, | |
COLLECTION_NAME, | |
REQUIRED_FIELDS, | |
REQUIRED_FIELDS_DEFAULTS | |
) | |
logger = logging.getLogger('fabric_to_espanso') | |
class DatabaseConfig: | |
"""Database configuration settings.""" | |
url: str = QDRANT_URL | |
max_retries: int = 3 | |
retry_delay: float = 1.0 | |
timeout: float = 10.0 | |
api_key: Optional[str] = None | |
required_fields: list = field(default_factory=lambda: REQUIRED_FIELDS) | |
required_fields_defaults: dict = field(default_factory=lambda: REQUIRED_FIELDS_DEFAULTS) | |
def validate(self) -> None: | |
"""Validate the database configuration. | |
Raises: | |
ConfigurationError: If any configuration values are invalid. | |
""" | |
try: | |
result = urlparse(self.url) | |
if not all([result.scheme, result.netloc]): | |
raise ValueError(f"Invalid database URL: {self.url}") | |
if self.max_retries < 0: | |
raise ValueError(f"max_retries must be >= 0, got {self.max_retries}") | |
if self.retry_delay <= 0: | |
raise ValueError(f"retry_delay must be > 0, got {self.retry_delay}") | |
if self.timeout <= 0: | |
raise ValueError(f"timeout must be > 0, got {self.timeout}") | |
except ValueError as e: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError(str(e)) | |
class EmbeddingModelConfig: | |
"""Embedding model configuration.""" | |
use_fastembed: bool = USE_FASTEMBED | |
collection_name: str = COLLECTION_NAME | |
dense_model_name: str = EMBED_MODEL_DENSE | |
sparse_model_name: str = EMBED_MODEL_SPARSE | |
def validate(self) -> None: | |
"""Validate the embedding configuration.""" | |
if not self.dense_model_name: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("Dense Embedding model name cannot be empty") | |
if not self.sparse_model_name: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("Sparse Embedding model name cannot be empty") | |
class Config: | |
"""Global configuration singleton.""" | |
_instance: Optional['Config'] = None | |
def __new__(cls) -> 'Config': | |
if cls._instance is None: | |
cls._instance = super().__new__(cls) | |
cls._instance.database = DatabaseConfig() | |
cls._instance.embedding = EmbeddingModelConfig() | |
cls._instance.espanso_trigger = DEFAULT_TRIGGER | |
cls._instance.fabric_patterns_folder = FABRIC_PATTERNS_FOLDER | |
cls._instance.yaml_output_folder = YAML_OUTPUT_FOLDER | |
cls._instance.obsidian_output_folder = OBSIDIAN_OUTPUT_FOLDER | |
cls._instance.obsidian_input_folder = OBSIDIAN_INPUT_FOLDER | |
cls._instance.base_words = BASE_WORDS | |
return cls._instance | |
def validate(self) -> None: | |
"""Validate all configuration settings.""" | |
self.database.validate() | |
self.embedding.validate() | |
# Validate paths | |
if not self.espanso_trigger: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("The default trigger for espanso patterns cannot be empty") | |
if not self.fabric_patterns_folder: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("The fabric patterns folder path cannot be empty") | |
if not self.yaml_output_folder: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("YAML output folder path for espanso cannot be empty") | |
if not self.obsidian_output_folder: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("Obsidian output folder path to write the files for Obsidian Textgenerator cannot be empty") | |
if not self.obsidian_input_folder: | |
from .exceptions import ConfigurationError | |
raise ConfigurationError("Obsidian input folder path to find the personal prompts stored in Obsidian cannot be empty") | |
for path in [self.fabric_patterns_folder, self.yaml_output_folder, self.obsidian_output_folder, self.obsidian_input_folder]: | |
if not path == "cloud_dummy" and not Path(path).is_dir(): | |
from .exceptions import ConfigurationError | |
raise ConfigurationError(f"{path} is not a valid directory") | |
# Global configuration instance | |
config = Config() | |