Another implementation of undo/redo

This commit is contained in:
2025-07-31 22:54:09 +02:00
parent 72f5f30da6
commit 37c91d0d5d
13 changed files with 228 additions and 94 deletions

View File

@@ -271,6 +271,42 @@ class DbEngine:
except KeyError:
raise DbException(f"Key '{key}' not found in entry '{entry}'")
def history(self, user_id, entry, digest=None, max_items=1000):
"""
Gives the current digest and all its ancestors
:param user_id:
:param entry:
:param digest:
:param max_items:
:return:
"""
with self.lock:
logger.info(f"History for {user_id=}, {entry=}, {digest=}")
digest_to_use = digest or self._get_entry_digest(user_id, entry)
logger.debug(f"Using digest {digest_to_use}.")
count = 0
history = []
while True:
if count >= max_items or digest_to_use is None:
break
history.append(digest_to_use)
count += 1
try:
target_file = self._get_obj_path(user_id, digest_to_use)
with open(target_file, 'r', encoding='utf-8') as file:
as_dict = json.load(file)
digest_to_use = as_dict[TAG_PARENT][0]
except FileNotFoundError:
break
return history
def debug_root(self):
"""
Lists all folders in the root directory
@@ -312,7 +348,7 @@ class DbEngine:
return []
return [f for f in os.listdir(self.root) if os.path.isdir(os.path.join(self.root, f)) and f != 'refs']
def debug_get_digest(self, user_id, entry):
def get_digest(self, user_id, entry):
return self._get_entry_digest(user_id, entry)
def _serialize(self, obj):

View File

@@ -98,10 +98,10 @@ class SettingsManager:
user_id, user_email = self._get_user(session)
return self._db_engine.save(user_id, user_email, entry, obj)
def load(self, session: dict, entry: str, default=NoDefault):
def load(self, session: dict, entry: str, digest=None, default=NoDefault):
user_id, _ = self._get_user(session)
try:
return self._db_engine.load(user_id, entry)
return self._db_engine.load(user_id, entry, digest)
except DbException:
return default
@@ -128,6 +128,14 @@ class SettingsManager:
return self._db_engine.exists(user_id, entry)
def get_digest(self, session: dict, entry: str):
user_id, _ = self._get_user(session)
return self._db_engine.get_digest(user_id, entry)
def history(self, session, entry, digest=None, max_items=1000):
user_id, _ = self._get_user(session)
return self._db_engine.history(user_id, entry, digest, max_items)
def get_db_engine(self):
return self._db_engine
@@ -177,7 +185,7 @@ class GenericDbManager:
if key.startswith("_"):
super().__setattr__(key, value)
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
settings = self._settings_manager.load(self._session, self._obj_entry, default=self._obj_type())
if not (hasattr(settings, key)):
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{key}'.")
@@ -188,7 +196,7 @@ class GenericDbManager:
if item.startswith("_"):
return super().__getattribute__(item)
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
settings = self._settings_manager.load(self._session, self._obj_entry, default=self._obj_type())
if not (hasattr(settings, item)):
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{item}'.")
@@ -250,7 +258,7 @@ class NestedSettingsManager:
self._settings_manager.save(self._session, self._obj_entry, settings)
def _get_settings_and_object(self):
settings = self._settings_manager.load(self._session, self._obj_entry, self._obj_type())
settings = self._settings_manager.load(self._session, self._obj_entry, default=self._obj_type())
if not hasattr(settings, self._obj_attribute):
raise AttributeError(f"Settings '{self._obj_entry}' has no attribute '{self._obj_attribute}'.")