From 08d45f9330673debd846152897bb1b7d549d9f99 Mon Sep 17 00:00:00 2001 From: Jordi Date: Mon, 25 Mar 2024 15:56:40 +0100 Subject: [PATCH] server.py: Fail gracefully when serializing/deserializing a tree. Currently, t.explore() will dump the tree to /tmp/*tid*.pickle, and use it if to "undo" an ultrametric visualization (by reloading the original tree from disk). Sometimes the trees cannot be pickled, and this was not considered. Now at least it fails gracefully. But I think we would be better by not dumping the tree at all, and not allowing the visualization of trees to modify the tree itself and pretend that it is not. Editing the tree should be explicit. --- ete4/smartview/gui/server.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ete4/smartview/gui/server.py b/ete4/smartview/gui/server.py index 8b1bcbb6..f9a21081 100755 --- a/ete4/smartview/gui/server.py +++ b/ete4/smartview/gui/server.py @@ -732,11 +732,20 @@ def retrieve_tree_data(tid): It retrieves all that from a previously saved pickle file in /tmp.""" # Called when tree has been deleted from memory. - tree_data = pickle.load(open(f'/tmp/{tid}.pickle', 'rb')) + try: + tree_data = pickle.load(open(f'/tmp/{tid}.pickle', 'rb')) + except (FileNotFoundError, EOFError, pickle.UnpicklingError) as e: + print(f'Tree {tid} cannot be recovered from disk. Loading placeholder.') + tree_data = TreeData() + tree_data.name = 'Placeholder tree' + tree_data.tree = Tree('(could,not,load,tree);') + ops.update_sizes_all(tree_data.tree) + tree_data.style = copy_style(TreeStyle()) tree_data.layouts = retrieve_layouts(tree_data.layouts) tree_data.active = drawer_module.get_empty_active() tree_data.timer = time() # to track if it is active + return tree_data @@ -1445,7 +1454,12 @@ def write_tree_data(): data.style = None # since it can't be pickled data.layouts = layouts # same data.active = None # same - pickle.dump(data, open(f'/tmp/{tid}.pickle', 'wb')) + try: + pickle.dump(data, open(f'/tmp/{tid}.pickle', 'wb')) + except (pickle.PicklingError, PermissionError) as e: + print(f'Tree {tid} not saved to file.') + # So changing to ultrametric and back will not work, + # because it is done by re-reading from the dumped file. thr_write = Thread(daemon=True, target=write_tree_data) # so we are not delayed thr_write.start() # by big trees