refactor(config): abstract config storage and enable dependency injection

Abstract the configuration storage mechanism to allow using custom
configurations, such as in-memory setups, when using the tool as
a library. This aligns the configuration architecture with the
session cache abstraction.

- Define ConfigInterface protocol and InMemoryConfig class
- Make CacheFile, InMemoryCache, ConfigFile, and InMemoryConfig
  explicitly inherit their interfaces
- Update MdrsService and MdrsClient to accept customizable
  config_class and config instances
- Add validation to check remote parameter consistency in
  create_connection
- Remove unused imports across command files
This commit is contained in:
2026-07-02 23:30:33 +09:00
parent 8ce9e09e69
commit b95fc0cd7d
7 changed files with 78 additions and 34 deletions
+52 -2
View File
@@ -1,6 +1,7 @@
import configparser
import os
from typing import Final
import threading
from typing import Final, Protocol, runtime_checkable
import validators
@@ -9,7 +10,56 @@ from mdrsclient.settings import CONFIG_DIRNAME
from mdrsclient.utils import FileLock
class ConfigFile:
@runtime_checkable
class ConfigInterface(Protocol):
remote: str
def list(self) -> list[tuple[str, str]]: ...
@property
def url(self) -> str | None: ...
@url.setter
def url(self, url: str) -> None: ...
@url.deleter
def url(self) -> None: ...
class InMemoryConfig(ConfigInterface):
__configs: dict[str, str] = {}
__lock: threading.Lock = threading.Lock()
remote: str
def __init__(self, remote: str) -> None:
self.remote = remote
def list(self) -> list[tuple[str, str]]:
with self.__lock:
return list(self.__configs.items())
@property
def url(self) -> str | None:
with self.__lock:
return self.__configs.get(self.remote)
@url.setter
def url(self, url: str) -> None:
if not validators.url(url):
raise IllegalArgumentException("malformed URI sequence")
with self.__lock:
self.__configs[self.remote] = url
@url.deleter
def url(self) -> None:
with self.__lock:
if self.remote in self.__configs:
del self.__configs[self.remote]
@classmethod
def clear(cls) -> None:
with cls.__lock:
cls.__configs.clear()
class ConfigFile(ConfigInterface):
OPTION_URL: Final[str] = "url"
CONFIG_FILENAME: Final[str] = "config.ini"
remote: str