Change json and toml file API

This commit is contained in:
Joscha 2025-11-05 02:07:43 +01:00
parent 862a9c1683
commit c7f7697f66
2 changed files with 64 additions and 30 deletions

View file

@ -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))

View file

@ -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: