104 lines
2.8 KiB
Python
104 lines
2.8 KiB
Python
import os
|
|
import json
|
|
import atexit
|
|
from threading import Thread, Event
|
|
from collections.abc import MutableMapping
|
|
|
|
from PySide2 import QtCore
|
|
|
|
data_dir_path = os.path.join(QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.AppDataLocation),
|
|
"fimefracking")
|
|
|
|
tasks_path = os.path.join(data_dir_path, "tasks.json")
|
|
|
|
data_path = os.path.join(data_dir_path, "data_{}.json")
|
|
save_delay = 3 * 60
|
|
|
|
|
|
class Tasks:
|
|
def __init__(self):
|
|
if not os.path.exists(data_dir_path):
|
|
os.mkdir(data_dir_path)
|
|
if os.path.exists(tasks_path):
|
|
with open(tasks_path, "r") as f:
|
|
self._tasks = json.loads(f.read())
|
|
else:
|
|
self._tasks = []
|
|
|
|
@property
|
|
def tasks(self):
|
|
return self._tasks
|
|
|
|
@tasks.setter
|
|
def tasks(self, tasks):
|
|
self._tasks = tasks
|
|
self._save()
|
|
|
|
def _save(self):
|
|
print("...saving tasks...")
|
|
with open(tasks_path, "w+") as f:
|
|
f.write(json.dumps(self._tasks))
|
|
|
|
|
|
class Data(MutableMapping):
|
|
def __init__(self):
|
|
if not os.path.exists(data_dir_path):
|
|
os.mkdir(data_dir_path)
|
|
self._cache = {}
|
|
self._hot_keys = []
|
|
self._running = False
|
|
self._tevent = Event()
|
|
self._thread = None
|
|
|
|
def cleanup():
|
|
self._running = False
|
|
self._tevent.set()
|
|
if self._thread:
|
|
self._thread.join()
|
|
atexit.register(cleanup)
|
|
|
|
def __getitem__(self, key):
|
|
dpath = data_path.format(key)
|
|
if key not in self._cache and os.path.exists(dpath):
|
|
with open(dpath, "r") as f:
|
|
self._cache[key] = f.read()
|
|
return self._cache[key]
|
|
|
|
def __setitem__(self, key, value):
|
|
self._cache[key] = value
|
|
self._hot_keys.append(key)
|
|
self._schedule_save()
|
|
|
|
def _schedule_save(self):
|
|
if self._running:
|
|
return
|
|
self._running = True
|
|
self._thread = Thread(target=self._executor, daemon=True)
|
|
self._thread.start()
|
|
|
|
def _executor(self):
|
|
while self._running:
|
|
self._tevent.wait(save_delay)
|
|
self._save()
|
|
|
|
def _save(self):
|
|
for key in self._hot_keys:
|
|
print(f"... saving dict {key} ...")
|
|
to_write = self._cache[key] # apparently thread-safe
|
|
with open(data_path.format(key), "w+") as f:
|
|
f.write(json.dumps(to_write))
|
|
self._hot_keys = []
|
|
self._saving = False
|
|
|
|
def __delitem__(self, key):
|
|
print("WARNING: deletion of items not supported")
|
|
|
|
def __iter__(self):
|
|
return iter(self._cache)
|
|
|
|
def __len__(self):
|
|
return len(self._cache)
|
|
|
|
def __repr__(self):
|
|
return f"{type(self).__name__}({self._cache})"
|