From 29978f8082f9505a18d80b6ecbe6717a4ec6e5bf Mon Sep 17 00:00:00 2001 From: bleudev Date: Sun, 8 Sep 2024 22:38:26 +0300 Subject: [PATCH] JsonFileUpdater pre-final --- .gitignore | 1 + ufpy/__init__.py | 2 +- ufpy/path/__init__.py | 1 + ufpy/path/json_file_updater.py | 91 ++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 ufpy/path/json_file_updater.py diff --git a/.gitignore b/.gitignore index 1bf9e91..f86a76e 100644 --- a/.gitignore +++ b/.gitignore @@ -164,6 +164,7 @@ cython_debug/ # Tests tests.py +tests.json # PyPi .pypirc \ No newline at end of file diff --git a/ufpy/__init__.py b/ufpy/__init__.py index bd6db52..5059215 100644 --- a/ufpy/__init__.py +++ b/ufpy/__init__.py @@ -34,7 +34,7 @@ def new_func(*args, **kwargs): UStack = __deprecated("UStack", Stack, '0.2', '0.5') # Path package -__path_version__ = '0.1' +__path_version__ = '0.2' from ufpy.path import * # GitHub package diff --git a/ufpy/path/__init__.py b/ufpy/path/__init__.py index 738eddd..958d816 100644 --- a/ufpy/path/__init__.py +++ b/ufpy/path/__init__.py @@ -1,2 +1,3 @@ from ufpy.path.files import * +from ufpy.path.json_file_updater import * from ufpy.path.tools import * diff --git a/ufpy/path/json_file_updater.py b/ufpy/path/json_file_updater.py new file mode 100644 index 0000000..a75c087 --- /dev/null +++ b/ufpy/path/json_file_updater.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +__all__ = ( + 'JsonFileUpdater', +) + +from typing import Any, Generic, TypeVar +from ujson import dumps, loads + +VT = TypeVar('VT') + +class JsonFileUpdater(Generic[VT]): + def __init__(self, json_file_path: str, indent: int = 4) -> None: + self.path = json_file_path + self.indent = indent + self.__d: dict[str, VT] | None = None + + def __load(self) -> dict[str, VT]: + with open(self.path, encoding='utf-8') as f: + r = loads(f.read()) + return r + + def __write(self, d: dict[str, VT]) -> None: + with open(self.path, 'w', encoding='utf-8') as f: + f.write(dumps( + d, + ensure_ascii=False, + indent=self.indent + )) + + def __get_dict(self, path: str, __dict: dict[str, Any]) -> dict[str, Any]: + if not ' / ' in path: + return __dict + keys = path.split(' / ')[:-1] + + r = __dict + for i in keys: + r = r[i] + return r + + def __getitem__(self, key: str) -> VT: + if self.__d == None: + d = self.__load() + else: + d = self.__d + + keys = key.split(' / ') + + return self.__get_dict(key, d)[keys[-1]] + + def __setitem__(self, key: str, value: VT) -> None: + if self.__d == None: + d = self.__load() + + keys = key.split(' / ') + + r = d + for i in keys: + r.setdefault(i, {}) + r = r[i] + + d2 = self.__get_dict(key, d) + d2[keys[-1]] = value + + self.__write(d) + else: + keys = key.split(' / ') + + r = self.__d + for i in keys: + r.setdefault(i, {}) + r = r[i] + + d2 = self.__get_dict(key, self.__d) + d2[keys[-1]] = value + def __enter__(self) -> JsonFileUpdater: + self.__d = self.__load() + return self + + def __exit__(self, exception_type, exception_value, traceback) -> None: + self.__write(self.__d) + self.__d = None + + def __repr__(self) -> str: + if self.__d == None: + return dumps( + self.__load(), + ensure_ascii=False, + indent=self.indent + ) + return repr(self.__d)