Initial
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/.idea/
|
||||
/tests/
|
||||
|
||||
poetry.lock
|
||||
|
||||
*/__pycache__/
|
||||
1
README.md
Normal file
1
README.md
Normal file
@@ -0,0 +1 @@
|
||||
[nekomata is now in early-dev state](https://nekomata.kotikot.com/)
|
||||
4
neko_configparser/__init__.py
Normal file
4
neko_configparser/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .neko.interfaces import ConfigParserInterface
|
||||
|
||||
|
||||
__all__ = ['ConfigParserInterface']
|
||||
1
neko_configparser/modules/__init__.py
Normal file
1
neko_configparser/modules/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
pass
|
||||
19
neko_configparser/modules/toml_parser.py
Normal file
19
neko_configparser/modules/toml_parser.py
Normal 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))
|
||||
79
neko_configparser/modules/writer.py
Normal file
79
neko_configparser/modules/writer.py
Normal 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()
|
||||
1
neko_configparser/neko/__init__.py
Normal file
1
neko_configparser/neko/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
pass
|
||||
30
neko_configparser/neko/interfaces.py
Normal file
30
neko_configparser/neko/interfaces.py
Normal 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
17
pyproject.toml
Normal 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"
|
||||
Reference in New Issue
Block a user