Initial commit

This commit is contained in:
2026-02-23 22:48:25 +00:00
commit b8182ead88
46 changed files with 1845 additions and 0 deletions

View File

@@ -0,0 +1 @@
from .autosavedict import * # noqa

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,120 @@
from __future__ import annotations
import os
import json
from typing import (
Any,
Dict,
Tuple,
Mapping,
Optional,
Iterable,
MutableMapping,
)
__all__ = (
'AutoSaveDict',
)
class AutoSaveDict(dict[Any, Any]):
def __init__(self,
file_path: Optional[os.PathLike[Any]] = None,
**pairs: Any):
self.file_path = file_path
self.__default = pairs
if self.file_path is None:
self._pairs = pairs
elif not os.path.exists(self.file_path):
self._pairs = pairs
else:
self._pairs = self._read()
super(AutoSaveDict, self).__init__(**self._pairs)
def __setitem__(self, __key: Any, __value: Any) -> None:
data = self._read()
data[__key] = __value
self._write(data)
super().__setitem__(__key, __value)
def __delitem__(self, __key: Any) -> None:
data = self._read()
del data[__key]
self._write(data)
return super().__delitem__(__key)
def __or__(self, __value: Mapping[Any, Any]) -> AutoSaveDict:
data = self._pairs | __value
return AutoSaveDict(None, **data)
def _write(self, content: Dict[Any, Any]) -> None:
with open(self.file_path, mode='w') as f: # type: ignore
json.dump(content, f, indent=4)
self._pairs = content
def _read(self) -> Dict[Any, Any]:
with open(self.file_path, mode='r') as f: # type: ignore
data: Dict[Any, Any] = json.load(f)
return data
@classmethod
def fromkeys(cls, __iterable: Iterable[Any], __value: Any = None,
file_path: Optional[os.PathLike[Any]] = None) -> AutoSaveDict:
data = {}
for key in __iterable:
data[key] = __value
return cls(file_path, **data)
@classmethod
def frommapping(cls, __mapping: Mapping[Any, Any],
file_path: Optional[os.PathLike[Any]] = None)\
-> AutoSaveDict:
data = dict(__mapping)
return cls(file_path, **data)
@classmethod
def fromfile(cls, src: os.PathLike[Any],
dst: Optional[os.PathLike[Any]] = None) -> AutoSaveDict:
with open(src, mode='r') as f:
data = json.load(f)
return AutoSaveDict(dst, **data)
def init(self) -> None:
if not os.path.exists(self.file_path): # type: ignore
self._write(self._pairs)
else:
self._pairs = self._read()
def restore(self) -> None:
self.clear()
self.update(self.__default)
self.init()
def copy(self,
file_path: Optional[os.PathLike[Any]] = None) -> AutoSaveDict:
data = {}
for key, val in self.items():
data[key] = val
return AutoSaveDict(file_path, **data)
def pop(self, __key: Any) -> Any: # type: ignore
data = self._read()
data.pop(__key)
self._write(data)
return super().pop(__key)
def popitem(self) -> Tuple[Any, Any]:
key = tuple(self._read().keys())[-1]
value = self.pop(key)
super().popitem()
return (key, value)
def clear(self) -> None:
self._write({})
super().clear()
def update(self, __m: Mapping[Any, Any]) -> MutableMapping: # type: ignore
for k, v in __m.items():
self[k] = v
super().update(__m)

146
Bot/jsonwrapper/tests.py Normal file
View File

@@ -0,0 +1,146 @@
import os
import json
import unittest
from pathlib import Path
from .autosavedict import AutoSaveDict
BASE_DIR = f'{os.sep}'.join(__file__.split(os.sep)[:-1])
class TestAutoSaveDict(unittest.TestCase):
def setUp(self) -> None:
self.path = Path(BASE_DIR) / 'test.json'
self.default = {'a': 1, 'b': 2}
asd = AutoSaveDict(self.path, **self.default)
asd.init()
return super().setUp()
def tearDown(self) -> None:
os.remove(self.path)
return super().tearDown()
def test_init(self) -> None:
asd = AutoSaveDict(self.path, **self.default)
asd.init()
self.assertTrue(os.path.exists(self.path))
self.assertEqual(asd, self.default)
self.assertEqual(asd._pairs, self.default)
self.assertEqual(asd._read(), self.default)
def test_restore(self) -> None:
asd = AutoSaveDict(self.path, **self.default)
asd['c'] = 3
self.assertIn('c', asd)
asd.restore()
self.assertEqual(asd, self.default)
self.assertEqual(asd._read(), self.default)
self.assertEqual(asd._pairs, self.default)
def test_pop(self) -> None:
asd = AutoSaveDict(self.path, **self.default)
asd.init()
key = tuple(self.default.keys())[0]
asd.pop(key)
self.assertNotIn(key, asd._read())
self.assertNotIn(key, asd._pairs)
self.assertNotIn(key, asd)
def test_popitem(self) -> None:
asd = AutoSaveDict(self.path, **self.default)
asd.init()
key = tuple(asd.keys())[-1]
val = asd[key]
result = asd.popitem()
self.assertEqual(result, (key, val))
self.assertNotIn(key, asd)
self.assertNotIn(key, asd._read())
self.assertNotIn(key, asd._pairs)
def test_update(self) -> None:
asd = AutoSaveDict(self.path, **self.default)
asd.init()
new = {'b': 3}
asd.update(new)
self.assertEqual(asd['b'], new['b'])
self.assertEqual(asd._read()['b'], new['b'])
self.assertEqual(asd._pairs['b'], new['b'])
def test_copy(self) -> None:
copy_path = 'test_copy.json'
asd = AutoSaveDict(self.path, **self.default)
asd_copy = asd.copy(copy_path) # type: ignore
asd.init()
asd_copy.init()
self.assertEqual(asd_copy, asd)
self.assertEqual(asd_copy, asd._read())
self.assertEqual(asd_copy, asd._pairs)
os.remove(copy_path)
def test_fromfile(self) -> None:
file = 'test_fromfile.json'
config = {'b': 3, 'c': 4}
with open(file, mode='w') as f:
json.dump(config, f)
os.remove(self.path)
asd = AutoSaveDict.fromfile(file, self.path) # type: ignore
asd.init()
self.assertEqual(config, asd)
self.assertEqual(config, asd._pairs)
self.assertEqual(config, asd._read())
self.assertIsInstance(asd, AutoSaveDict)
os.remove(file)
def test_frommapping(self) -> None:
path = 'test_frommapping.json'
mapping = (
('a', 1),
('b', 2),
('c', 3),
)
expected = dict(mapping)
asd = AutoSaveDict.frommapping(mapping, path) # type: ignore
asd.init()
self.assertEqual(expected, asd)
self.assertEqual(expected, asd._read())
self.assertEqual(expected, asd._pairs)
os.remove(path)
def test_fromkeys(self) -> None:
path = 'test_fromkeys.json'
keys = 'test'
expected = dict.fromkeys(keys)
asd = AutoSaveDict.fromkeys(keys, file_path=path) # type: ignore
asd.init()
self.assertEqual(asd, expected)
self.assertEqual(asd._read(), expected)
self.assertEqual(asd._pairs, expected)
os.remove(path)
def test_setitem(self) -> None:
expected = {**self.default, "z": 3}
asd = AutoSaveDict(self.path, **self.default)
asd['z'] = 3
self.assertEqual(asd, expected)
self.assertEqual(asd._read(), expected)
self.assertEqual(asd._pairs, expected)
def test_delitem(self) -> None:
config = self.default.copy()
key = tuple(config.keys())[0]
asd = AutoSaveDict(self.path, **config)
asd.init()
del config[key]
del asd[key]
self.assertEqual(asd, config)
self.assertEqual(asd._read(), config)
self.assertEqual(asd._pairs, config)