Change json and toml file API
This commit is contained in:
parent
862a9c1683
commit
c7f7697f66
2 changed files with 64 additions and 30 deletions
|
|
@ -1,12 +1,28 @@
|
|||
from typing import Self
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, Self
|
||||
|
||||
from .file import TAG, File
|
||||
from .text import TextFile
|
||||
|
||||
|
||||
def _merge_values(a: Any, b: Any) -> Any:
|
||||
if not isinstance(a, dict) or not isinstance(b, dict):
|
||||
return b
|
||||
|
||||
result = {}
|
||||
for k, v_a in a.items():
|
||||
result[k] = v_a
|
||||
for k, v_b in b.items():
|
||||
v_a = a.get(k)
|
||||
if v_a is None:
|
||||
result[k] = v_b
|
||||
else:
|
||||
result[k] = _merge_values(v_a, v_b)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@dataclass
|
||||
class JsonFileProxy:
|
||||
file: "JsonFile"
|
||||
|
|
@ -15,18 +31,14 @@ class JsonFileProxy:
|
|||
def at(self, *path: str) -> Self:
|
||||
return JsonFileProxy(self.file, self.path + path)
|
||||
|
||||
def set(self, value: Any) -> None:
|
||||
if not self.path:
|
||||
self.file.set(value)
|
||||
def set(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
if isinstance(path, str):
|
||||
path = (path,)
|
||||
|
||||
data = self.file.data
|
||||
*parts, last = self.path
|
||||
for part in parts:
|
||||
data = data.setdefault(part, {})
|
||||
data[last] = value
|
||||
self.file.set(self.path + path, value)
|
||||
|
||||
def tag_here(self, tag: str = TAG) -> None:
|
||||
self.set(tag)
|
||||
def tag(self, path: str | tuple[str, ...] = "_tag") -> None:
|
||||
self.set(path, TAG)
|
||||
|
||||
|
||||
class JsonFile(File):
|
||||
|
|
@ -36,13 +48,32 @@ class JsonFile(File):
|
|||
def at(self, *path: str) -> JsonFileProxy:
|
||||
return JsonFileProxy(self, path)
|
||||
|
||||
def set(self, value: Any) -> None:
|
||||
self.data = value
|
||||
def get(self, path: str | tuple[str, ...]) -> Any:
|
||||
data = self.data
|
||||
for part in path:
|
||||
data = data[part]
|
||||
return data
|
||||
|
||||
def tag(self, tag: str = TAG, key: str | list[str] = "_tag") -> None:
|
||||
if isinstance(key, str):
|
||||
self.at(key).tag_here(tag=tag)
|
||||
self.at(*key).tag_here(tag=tag)
|
||||
def set(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
if isinstance(path, str):
|
||||
path = (path,)
|
||||
|
||||
if not path:
|
||||
self.data = value
|
||||
return
|
||||
|
||||
*parts, last = path
|
||||
|
||||
data = self.data
|
||||
for part in parts:
|
||||
data = data.setdefault(part, {})
|
||||
data[last] = value
|
||||
|
||||
def merge(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
self.set(path, _merge_values(self.get(path), value))
|
||||
|
||||
def tag(self, path: str | tuple[str, ...] = "_tag") -> None:
|
||||
self.set(path, TAG)
|
||||
|
||||
def to_text(self) -> TextFile:
|
||||
return TextFile(json.dumps(self.data))
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from typing import Any, Self
|
|||
import toml
|
||||
|
||||
from .file import File
|
||||
from .json import JsonFile
|
||||
from .text import TextFile
|
||||
|
||||
|
||||
|
|
@ -15,31 +16,33 @@ class TomlFileProxy:
|
|||
def at(self, *path: str) -> Self:
|
||||
return TomlFileProxy(self.file, self.path + path)
|
||||
|
||||
def set(self, value: Any) -> None:
|
||||
if not self.path:
|
||||
self.file.set(value)
|
||||
def set(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
if isinstance(path, str):
|
||||
path = (path,)
|
||||
|
||||
data = self.file.data
|
||||
*parts, last = self.path
|
||||
for part in parts:
|
||||
data = data.setdefault(part, {})
|
||||
data[last] = value
|
||||
self.file.set(self.path + path, value)
|
||||
|
||||
|
||||
class TomlFile(File):
|
||||
def __init__(self, data: Any = {}) -> None:
|
||||
self.data = data
|
||||
self.json = JsonFile(data)
|
||||
|
||||
def at(self, *path: str) -> TomlFileProxy:
|
||||
return TomlFileProxy(self, path)
|
||||
|
||||
def set(self, value: Any) -> None:
|
||||
self.data = value
|
||||
def get(self, path: str | tuple[str, ...]) -> Any:
|
||||
return self.json.get(path)
|
||||
|
||||
def set(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
self.json.set(path, value)
|
||||
|
||||
def merge(self, path: str | tuple[str, ...], value: Any) -> None:
|
||||
self.json.merge(path, value)
|
||||
|
||||
def to_text(self) -> TextFile:
|
||||
file = TextFile()
|
||||
file.tag(comment="#")
|
||||
file.append(toml.dumps(self.data), newline=False)
|
||||
file.append(toml.dumps(self.json.data), newline=False)
|
||||
return file
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue