diff --git a/molecularnodes/io/parse/mda.py b/molecularnodes/io/parse/mda.py index 98dece0a..c8df734c 100644 --- a/molecularnodes/io/parse/mda.py +++ b/molecularnodes/io/parse/mda.py @@ -150,7 +150,7 @@ def bonds(self) -> List[List[int]]: def elements(self) -> List[str]: try: elements = self.ag.elements.tolist() - except: + except AttributeError: # If 'elements' attribute doesn't exist try: elements = [ x @@ -158,8 +158,10 @@ def elements(self) -> List[str]: else mda.topology.guessers.guess_atom_element(x) for x in self.ag.atoms.names ] - - except: + except ( + KeyError, + ValueError, + ): # If 'x' is not in 'data.elements.keys()' or 'guess_atom_element(x)' fails elements = ["X"] * self.ag.n_atoms return elements @@ -671,7 +673,13 @@ def in_memory( if add_occupancy: try: obj.set_attribute(frame, "occupancy", ts.data["occupancy"]) - except: + except KeyError: + print("KeyError: 'occupancy' not found in ts.data") + add_occupancy = False + except TypeError: + print( + "TypeError: ts.data is not a dictionary or similar mapping type" + ) add_occupancy = False # disable the frames collection from the viewer diff --git a/molecularnodes/io/parse/molecule.py b/molecularnodes/io/parse/molecule.py index 85f49df4..1f825720 100644 --- a/molecularnodes/io/parse/molecule.py +++ b/molecularnodes/io/parse/molecule.py @@ -679,9 +679,11 @@ def att_sec_struct(): ) if verbose: print(f'Added {att["name"]} after {time.process_time() - start} s') - except: + except (TypeError, KeyError) as e: if verbose: - warnings.warn(f"Unable to add attribute: {att['name']}") + warnings.warn( + f"Unable to add attribute: {att['name']}. Error: {str(e)}" + ) print( f'Failed adding {att["name"]} after {time.process_time() - start} s' ) diff --git a/molecularnodes/ui/panel.py b/molecularnodes/ui/panel.py index 79fb4c4c..41f87f0b 100644 --- a/molecularnodes/ui/panel.py +++ b/molecularnodes/ui/panel.py @@ -119,7 +119,7 @@ def panel_object(layout, context): if mol_type == "md": layout.prop(object.mn, "subframes") if mol_type == "star": - layout.label(text=f"Ensemble") + layout.label(text="Ensemble") box = layout.box() ui_from_node(box, nodes.get_star_node(object)) return diff --git a/molecularnodes/utils.py b/molecularnodes/utils.py index dd6e3bca..b78c42c3 100644 --- a/molecularnodes/utils.py +++ b/molecularnodes/utils.py @@ -117,16 +117,32 @@ def _install_template(filepath, subfolder="", overwrite=True): if not os.path.isdir(path_app_templates): try: os.makedirs(path_app_templates, exist_ok=True) - except: + except PermissionError: + print( + "Permission denied: You do not have the necessary permissions to create the directory." + ) + traceback.print_exc() + except OSError as e: + print(f"OS error: {e}") traceback.print_exc() app_templates_old = set(os.listdir(path_app_templates)) - # check to see if the file is in compressed format (.zip) if zipfile.is_zipfile(filepath): try: file_to_extract = zipfile.ZipFile(filepath, "r") - except: + except FileNotFoundError: + print("File not found: The specified file does not exist.") + traceback.print_exc() + return {"CANCELLED"} + except PermissionError: + print( + "Permission denied: You do not have the necessary permissions to open the file." + ) + traceback.print_exc() + return {"CANCELLED"} + except zipfile.BadZipFile: + print("Bad zip file: The file is not a zip file or it is corrupted.") traceback.print_exc() return {"CANCELLED"} @@ -143,7 +159,14 @@ def _install_template(filepath, subfolder="", overwrite=True): try: # extract the file to "bl_app_templates_user" file_to_extract.extractall(path_app_templates) - except: + except PermissionError: + print( + "Permission denied: You do not have the necessary permissions to write to the directory." + ) + traceback.print_exc() + return {"CANCELLED"} + except OSError as e: + print(f"OS error: {e}") traceback.print_exc() return {"CANCELLED"} diff --git a/tests/test_mda.py b/tests/test_mda.py index a34dbc5e..ce304f19 100644 --- a/tests/test_mda.py +++ b/tests/test_mda.py @@ -47,7 +47,7 @@ def test_create_mda_session(self, mda_session): def reload_mda_session(self, mda_session): with pytest.warns(UserWarning, match="The existing mda session"): - mda_session_2 = mn.mda.create_session() + mn.mda.create_session() @pytest.mark.parametrize("in_memory", [False, True]) def test_show_universe( @@ -281,7 +281,7 @@ def test_create_mda_session(self, mda_session): def reload_mda_session(self, mda_session): with pytest.warns(UserWarning, match="The existing mda session"): - mda_session_2 = mn.mda.create_session() + mn.mda.create_session() def test_frame_mapping(self, mda_session, universe): remove_all_molecule_objects(mda_session) diff --git a/tests/test_nodes.py b/tests/test_nodes.py index f10c6a23..8f1a71a1 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -168,7 +168,6 @@ def test_color_entity(snapshot_custom: NumpySnapshotExtension): def get_links(sockets): - links = [] for socket in sockets: for link in socket.links: yield link diff --git a/tests/test_star.py b/tests/test_star.py index 7cb5c78f..424c13dd 100644 --- a/tests/test_star.py +++ b/tests/test_star.py @@ -1,6 +1,7 @@ import bpy import pytest import starfile +import importlib from scipy.spatial.transform import Rotation as R import molecularnodes as mn @@ -29,9 +30,7 @@ def test_starfile_attributes(type): ].to_numpy() # Calculate Scipy rotation from the euler angles - rot_from_euler = quats = R.from_euler( - seq="ZYZ", angles=euler_angles, degrees=True - ).inv() + rot_from_euler = R.from_euler(seq="ZYZ", angles=euler_angles, degrees=True).inv() # Activate the rotation debug mode in the nodetreee and get the quaternion attribute debugnode = mn.blender.nodes.star_node(ensemble.node_group).node_tree.nodes[ @@ -83,7 +82,9 @@ def test_micrograph_loading(): assert ensemble.star_node.inputs["Micrograph"].default_value.name == "montage.tiff" -@pytest.mark.skipif(SKIP, reason="Test may segfault on GHA") +@pytest.mark.skipif( + importlib.util.find_spec("pyopenvdb"), reason="Test may segfault on GHA" +) def test_rehydration(tmp_path): bpy.ops.wm.read_homefile() ensemble = mn.io.star.load(data_dir / "cistem.star")