This commit is contained in:
hhh
2024-02-02 21:53:35 +02:00
commit 90ed21c4a5
9 changed files with 158 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
/.idea/
/tests/
poetry.lock
*/__pycache__/

1
README.md Normal file
View File

@@ -0,0 +1 @@
[nekomata is now in early-dev state](https://nekomata.kotikot.com/)

View File

@@ -0,0 +1,4 @@
from .neko.interfaces import ConfigParserInterface
__all__ = ['ConfigParserInterface']

View File

@@ -0,0 +1 @@
pass

View File

@@ -0,0 +1,19 @@
import toml
class TomlConfig(dict):
def __init__(self, config_path: str = 'config.neko.toml', _config: dict = None):
try:
if _config is None:
super().__init__(**toml.load(config_path))
else:
super().__init__(**_config)
except FileNotFoundError:
super().__init__()
def __getattr__(self, item):
if type(self.get(item)) is not dict:
return self.get(item)
else:
return TomlConfig(_config=self.get(item))

View File

@@ -0,0 +1,79 @@
import toml
from typing import Dict, Any
def _update_dicts(dict1, dict2):
"""
Ensures that dict1 exists in dict2 or merges them in right way
"""
for key in dict1:
if key not in dict2 and not isinstance(dict1[key], WriteTomlConfig):
dict2[key] = dict1[key]
elif isinstance(dict1[key], dict) and isinstance(dict2[key], dict):
_update_dicts(dict1[key], dict2[key])
class WriteTomlConfig(dict):
def __init__(self, filename: str = 'config.neko.toml'):
self.__filename = filename
self.__parent = None
super().__init__()
self.__load_from_file(filename)
@classmethod
def __create_subsidiary(cls, data, parent):
d = cls(None) # type: ignore
d.__parent = parent
for key, value in data.items():
if isinstance(value, dict):
d[key] = cls.__create_subsidiary(value, parent=parent)
return d
def __getitem__(self, key):
val = super().__getitem__(key)
return val
def __setitem__(self, key, value):
if isinstance(value, dict):
value = type(self).__create_subsidiary(value, parent=self)
super().__setitem__(key, value)
self.__propagate_write()
def __delitem__(self, key):
super().__delitem__(key)
self.__propagate_write()
def __propagate_write(self):
if self.__parent:
self.__parent.__propagate_write()
else:
self.__write()
def to_dict(self):
standard_dict = {}
for key, value in self.items():
if isinstance(value, type(self)):
standard_dict[key] = value.to_dict()
else:
standard_dict[key] = value
return standard_dict
def __write(self):
with open(self.__filename, 'w') as f:
toml.dump(self.to_dict(), f)
def __load_from_file(self, filename=None):
if not filename:
return
try:
data = toml.load(filename)
for key, value in data.items():
self[key] = value
except FileNotFoundError:
open(filename, 'w+').close()
def ensure(self, data: Dict[str, Any]):
_update_dicts(data, self)
self.__propagate_write()

View File

@@ -0,0 +1 @@
pass

View File

@@ -0,0 +1,30 @@
from ..modules.toml_parser import TomlConfig
from ..modules.writer import WriteTomlConfig
from typing import Dict, Any
class ConfigParserInterface:
@staticmethod
def parse_config(config_path: str = 'config.neko.toml') -> TomlConfig:
"""
Get toml configuration in our handy representation
:param config_path:
:return:
"""
return TomlConfig(config_path)
@staticmethod
def ensure_config(
partition: str,
module_config: Dict[str, Any],
config_path: str = 'config.neko.toml'
) -> None:
"""
Validates your module config and adds values if needed
:param partition: Your module name or any name under which you want to see this
key-value configuration table
:param module_config: Dictionary of default config keys and values, so they will
be added and verified in config
:param config_path: Path of config, if you want to use custom
"""
WriteTomlConfig(config_path).ensure({partition: module_config})

17
pyproject.toml Normal file
View File

@@ -0,0 +1,17 @@
[tool.poetry]
name = "neko-configparser"
version = "0.1.0"
description = ""
authors = ["hhh"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11"
toml = "^0.10.2"
[tool.poetry.group.dev.dependencies]
rich = "^13.7.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"