MoleditPy-linux 4.8.1__tar.gz → 4.8.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/PKG-INFO +4 -4
  2. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/README.md +3 -3
  3. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/pyproject.toml +1 -1
  4. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/PKG-INFO +4 -4
  5. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/core/mol_geometry.py +2 -2
  6. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/core/molecular_data.py +1 -1
  7. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/main.py +2 -2
  8. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/plugins/plugin_interface.py +12 -10
  9. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/plugins/plugin_manager.py +30 -15
  10. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/analysis_window.py +8 -5
  11. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/app_state.py +13 -7
  12. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/base_picking_dialog.py +2 -2
  13. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/calculation_worker.py +119 -34
  14. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/compute_logic.py +23 -6
  15. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/constrained_optimization_dialog.py +7 -5
  16. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/custom_interactor_style.py +4 -1
  17. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/custom_qt_interactor.py +5 -0
  18. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/dialog_3d_picking_mixin.py +8 -1
  19. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/edit_actions_logic.py +22 -4
  20. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/export_logic.py +2 -2
  21. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/io_logic.py +27 -8
  22. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/main_window_init.py +1 -1
  23. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/molecular_scene_handler.py +4 -4
  24. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/molecule_scene.py +6 -2
  25. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/move_group_dialog.py +3 -3
  26. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/move_selected_atoms_dialog.py +3 -3
  27. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/planarize_dialog.py +1 -1
  28. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/plugin_menu_manager.py +3 -1
  29. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/string_importers.py +7 -7
  30. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/template_preview_item.py +2 -2
  31. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/translation_dialog.py +14 -2
  32. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/view_3d_logic.py +20 -20
  33. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/LICENSE +0 -0
  34. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/setup.cfg +0 -0
  35. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/SOURCES.txt +0 -0
  36. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/dependency_links.txt +0 -0
  37. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/entry_points.txt +0 -0
  38. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/requires.txt +0 -0
  39. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/MoleditPy_linux.egg-info/top_level.txt +0 -0
  40. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/__init__.py +0 -0
  41. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/__main__.py +0 -0
  42. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/assets/file_icon.ico +0 -0
  43. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/assets/icon.icns +0 -0
  44. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/assets/icon.ico +0 -0
  45. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/assets/icon.png +0 -0
  46. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/core/__init__.py +0 -0
  47. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/plugins/__init__.py +0 -0
  48. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/plugins/plugin_manager_window.py +0 -0
  49. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/__init__.py +0 -0
  50. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/about_dialog.py +0 -0
  51. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/align_plane_dialog.py +0 -0
  52. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/alignment_dialog.py +0 -0
  53. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/angle_dialog.py +0 -0
  54. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/atom_item.py +0 -0
  55. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/atom_picking.py +0 -0
  56. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/bond_item.py +0 -0
  57. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/bond_length_dialog.py +0 -0
  58. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/chain_mixin.py +0 -0
  59. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/color_settings_dialog.py +0 -0
  60. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/dialog_logic.py +0 -0
  61. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/dihedral_dialog.py +0 -0
  62. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/edit_3d_logic.py +0 -0
  63. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/geometry_base_dialog.py +0 -0
  64. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/main_window.py +0 -0
  65. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/mirror_dialog.py +0 -0
  66. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/periodic_table_dialog.py +0 -0
  67. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/preview_molecule.py +0 -0
  68. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_dialog.py +0 -0
  69. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_tabs/__init__.py +0 -0
  70. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_tabs/settings_2d_tab.py +0 -0
  71. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_tabs/settings_3d_tabs.py +0 -0
  72. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_tabs/settings_other_tab.py +0 -0
  73. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/settings_tabs/settings_tab_base.py +0 -0
  74. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/template_preview_view.py +0 -0
  75. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/ui_manager.py +0 -0
  76. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/user_template_dialog.py +0 -0
  77. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/ui/zoomable_view.py +0 -0
  78. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/__init__.py +0 -0
  79. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/constants.py +0 -0
  80. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/default_settings.py +0 -0
  81. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/hit_radius.py +0 -0
  82. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/sip_isdeleted_safe.py +0 -0
  83. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/suppress_log.py +0 -0
  84. {moleditpy_linux-4.8.1 → moleditpy_linux-4.8.3}/src/moleditpy_linux/utils/system_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy-linux
3
- Version: 4.8.1
3
+ Version: 4.8.3
4
4
  Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
5
5
  Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -709,9 +709,9 @@ Dynamic: license-file
709
709
  [![Python Versions](https://img.shields.io/pypi/pyversions/MoleditPy.svg)](https://pypi.org/project/MoleditPy/)
710
710
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
711
711
  [![Build Status](https://github.com/HiroYokoyama/python_molecular_editor/actions/workflows/tests.yml/badge.svg)](https://github.com/HiroYokoyama/python_molecular_editor/actions)
712
- ![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)
713
- ![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)
714
- ![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)
712
+ [![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/coverage_report.md)
713
+ [![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/MANUAL_CHECKLIST.md)
714
+ [![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/pylint-score.txt)
715
715
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/moleditpy)
716
716
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=monthly+downloads)](https://pepy.tech/projects/moleditpy)
717
717
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/HiroYokoyama/python_molecular_editor)
@@ -6,9 +6,9 @@
6
6
  [![Python Versions](https://img.shields.io/pypi/pyversions/MoleditPy.svg)](https://pypi.org/project/MoleditPy/)
7
7
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
8
8
  [![Build Status](https://github.com/HiroYokoyama/python_molecular_editor/actions/workflows/tests.yml/badge.svg)](https://github.com/HiroYokoyama/python_molecular_editor/actions)
9
- ![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)
10
- ![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)
11
- ![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)
9
+ [![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/coverage_report.md)
10
+ [![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/MANUAL_CHECKLIST.md)
11
+ [![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/pylint-score.txt)
12
12
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/moleditpy)
13
13
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=monthly+downloads)](https://pepy.tech/projects/moleditpy)
14
14
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/HiroYokoyama/python_molecular_editor)
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "MoleditPy-linux"
7
7
 
8
- version = "4.8.1"
8
+ version = "4.8.3"
9
9
 
10
10
  license = {file = "LICENSE"}
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy-linux
3
- Version: 4.8.1
3
+ Version: 4.8.3
4
4
  Summary: A cross-platform, simple, and intuitive molecular structure editor built in Python. It allows 2D molecular drawing and 3D structure visualization. It supports exporting structure files for input to DFT calculation software.
5
5
  Author-email: HiroYokoyama <titech.yoko.hiro@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -709,9 +709,9 @@ Dynamic: license-file
709
709
  [![Python Versions](https://img.shields.io/pypi/pyversions/MoleditPy.svg)](https://pypi.org/project/MoleditPy/)
710
710
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
711
711
  [![Build Status](https://github.com/HiroYokoyama/python_molecular_editor/actions/workflows/tests.yml/badge.svg)](https://github.com/HiroYokoyama/python_molecular_editor/actions)
712
- ![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)
713
- ![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)
714
- ![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)
712
+ [![Overall Coverage](https://img.shields.io/badge/coverage->80%25-green)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/coverage_report.md)
713
+ [![GUI Status](https://img.shields.io/badge/GUI-Manually_Verified-blue)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/MANUAL_CHECKLIST.md)
714
+ [![Pylint Score](https://img.shields.io/badge/pylint->9%2F10-brightgreen)](https://github.com/HiroYokoyama/python_molecular_editor/blob/main/tests/pylint-score.txt)
715
715
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads)](https://pepy.tech/projects/moleditpy)
716
716
  [![PyPI Downloads](https://static.pepy.tech/personalized-badge/moleditpy?period=monthly&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=monthly+downloads)](https://pepy.tech/projects/moleditpy)
717
717
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/HiroYokoyama/python_molecular_editor)
@@ -593,9 +593,9 @@ def _identify_problems_rdkit(
593
593
 
594
594
  def optimize_2d_coords(mol: Chem.Mol) -> Dict[int, Tuple[float, float]]:
595
595
  """Generate 2D coordinates using RDKit and return a map of (x, y) tuples."""
596
- from rdkit.Chem import AllChem
596
+ from rdkit.Chem import rdDepictor
597
597
 
598
- AllChem.Compute2DCoords(mol)
598
+ rdDepictor.Compute2DCoords(mol)
599
599
  conf = mol.GetConformer()
600
600
  new_positions = {}
601
601
  for rdkit_atom in mol.GetAtoms():
@@ -18,7 +18,7 @@ from rdkit import Chem
18
18
  from ..utils.constants import ANGSTROM_PER_PIXEL
19
19
 
20
20
 
21
- class PointTuple(tuple):
21
+ class PointTuple(Tuple[float, ...]):
22
22
  """Backward-compatible tuple that allows .x() and .y() access like QPointF."""
23
23
 
24
24
  def x(self) -> float:
@@ -20,7 +20,7 @@ import sys
20
20
  import argparse
21
21
  import time
22
22
  import traceback
23
- from typing import Any, Dict, Optional
23
+ from typing import Any, Dict, Optional, Set
24
24
 
25
25
  from .utils.constants import VERSION
26
26
 
@@ -81,7 +81,7 @@ class _ErrorDialogHandler(logging.Handler):
81
81
  # signature -> monotonic timestamp of its last shown dialog.
82
82
  self._last_shown: Dict[str, float] = {}
83
83
  # Held so a non-blocking box is not garbage-collected before it closes.
84
- self._open_boxes: set = set()
84
+ self._open_boxes: Set[QMessageBox] = set()
85
85
  self._log_path = log_path
86
86
 
87
87
  def emit(self, record: logging.LogRecord) -> None:
@@ -27,7 +27,7 @@ class PluginContext:
27
27
  def add_menu_action(
28
28
  self,
29
29
  path: str,
30
- callback: Callable,
30
+ callback: Callable[..., Any],
31
31
  text: Optional[str] = None,
32
32
  icon: Optional[str] = None,
33
33
  shortcut: Optional[str] = None,
@@ -57,8 +57,8 @@ class PluginContext:
57
57
  def register_menu_action(
58
58
  self,
59
59
  path: str,
60
- text_or_callback: Union[str, Callable],
61
- callback: Optional[Callable] = None,
60
+ text_or_callback: Union[str, Callable[..., Any]],
61
+ callback: Optional[Callable[..., Any]] = None,
62
62
  icon: Optional[str] = None,
63
63
  shortcut: Optional[str] = None,
64
64
  ) -> None:
@@ -76,7 +76,7 @@ class PluginContext:
76
76
  def add_plugin_menu(
77
77
  self,
78
78
  path: str,
79
- callback: Callable,
79
+ callback: Callable[..., Any],
80
80
  text: Optional[str] = None,
81
81
  icon: Optional[str] = None,
82
82
  shortcut: Optional[str] = None,
@@ -103,7 +103,7 @@ class PluginContext:
103
103
 
104
104
  def add_toolbar_action(
105
105
  self,
106
- callback: Callable,
106
+ callback: Callable[..., Any],
107
107
  text: str,
108
108
  icon: Optional[str] = None,
109
109
  tooltip: Optional[str] = None,
@@ -262,7 +262,7 @@ class PluginContext:
262
262
  if mw and hasattr(mw, "view_3d_manager") and mw.view_3d_manager.plotter:
263
263
  mw.view_3d_manager.plotter.reset_camera()
264
264
 
265
- def add_export_action(self, label: str, callback: Callable) -> None:
265
+ def add_export_action(self, label: str, callback: Callable[..., Any]) -> None:
266
266
  """
267
267
  Register a custom export action.
268
268
 
@@ -303,7 +303,7 @@ class PluginContext:
303
303
  self._plugin_name, extension, callback, priority
304
304
  )
305
305
 
306
- def add_analysis_tool(self, label: str, callback: Callable) -> None:
306
+ def add_analysis_tool(self, label: str, callback: Callable[..., Any]) -> None:
307
307
  """
308
308
  Register a tool in the Analysis menu.
309
309
 
@@ -313,7 +313,7 @@ class PluginContext:
313
313
  """
314
314
  self._manager.register_analysis_tool(self._plugin_name, label, callback)
315
315
 
316
- def register_save_handler(self, callback: Callable[[], dict]) -> None:
316
+ def register_save_handler(self, callback: Callable[[], Dict[str, Any]]) -> None:
317
317
  """
318
318
  Register a callback to save state into the project file.
319
319
 
@@ -322,7 +322,7 @@ class PluginContext:
322
322
  """
323
323
  self._manager.register_save_handler(self._plugin_name, callback)
324
324
 
325
- def register_load_handler(self, callback: Callable[[dict], None]) -> None:
325
+ def register_load_handler(self, callback: Callable[[Dict[str, Any]], None]) -> None:
326
326
  """
327
327
  Register a callback to restore state from the project file.
328
328
 
@@ -331,7 +331,9 @@ class PluginContext:
331
331
  """
332
332
  self._manager.register_load_handler(self._plugin_name, callback)
333
333
 
334
- def register_3d_context_menu(self, callback: Callable, label: str) -> None:
334
+ def register_3d_context_menu(
335
+ self, callback: Callable[..., Any], label: str
336
+ ) -> None:
335
337
  """Deprecated: This method does nothing. Kept for backward compatibility."""
336
338
  import warnings
337
339
 
@@ -92,8 +92,8 @@ class PluginManager:
92
92
  self.optimization_methods: Dict[str, Dict[str, Any]] = {}
93
93
  self.file_openers: Dict[str, List[Dict[str, Any]]] = {}
94
94
  self.analysis_tools: List[Dict[str, Any]] = []
95
- self.save_handlers: Dict[str, Callable] = {}
96
- self.load_handlers: Dict[str, Callable] = {}
95
+ self.save_handlers: Dict[str, Callable[..., Any]] = {}
96
+ self.load_handlers: Dict[str, Callable[..., Any]] = {}
97
97
  self.custom_3d_styles: Dict[str, Dict[str, Any]] = {}
98
98
  self.document_reset_handlers: List[Dict[str, Any]] = []
99
99
  self.atom_drag_handlers: List[Dict[str, Any]] = []
@@ -447,7 +447,7 @@ class PluginManager:
447
447
  self,
448
448
  plugin_name: str,
449
449
  path: str,
450
- callback: Callable,
450
+ callback: Callable[..., Any],
451
451
  text: str,
452
452
  icon: str,
453
453
  shortcut: str,
@@ -471,7 +471,12 @@ class PluginManager:
471
471
  )
472
472
 
473
473
  def register_toolbar_action(
474
- self, plugin_name: str, callback: Callable, text: str, icon: str, tooltip: str
474
+ self,
475
+ plugin_name: str,
476
+ callback: Callable[..., Any],
477
+ text: str,
478
+ icon: str,
479
+ tooltip: str,
475
480
  ) -> None:
476
481
  """Register a plugin toolbar button with its callback and display metadata."""
477
482
  self.toolbar_actions.append(
@@ -485,7 +490,7 @@ class PluginManager:
485
490
  )
486
491
 
487
492
  def register_drop_handler(
488
- self, plugin_name: str, callback: Callable, priority: int
493
+ self, plugin_name: str, callback: Callable[..., Any], priority: int
489
494
  ) -> None:
490
495
  """Register a drag-and-drop handler with a given priority."""
491
496
  self.drop_handlers.append(
@@ -495,7 +500,7 @@ class PluginManager:
495
500
  self.drop_handlers.sort(key=lambda x: x["priority"], reverse=True)
496
501
 
497
502
  def register_export_action(
498
- self, plugin_name: str, label: str, callback: Callable
503
+ self, plugin_name: str, label: str, callback: Callable[..., Any]
499
504
  ) -> None:
500
505
  """Register a plugin export action with its label and callback."""
501
506
  self.export_actions.append(
@@ -503,7 +508,7 @@ class PluginManager:
503
508
  )
504
509
 
505
510
  def register_optimization_method(
506
- self, plugin_name: str, method_name: str, callback: Callable
511
+ self, plugin_name: str, method_name: str, callback: Callable[..., Any]
507
512
  ) -> None:
508
513
  """Register a named 3D optimization method provided by a plugin."""
509
514
  method_key = method_name.upper()
@@ -520,7 +525,11 @@ class PluginManager:
520
525
  )
521
526
 
522
527
  def register_file_opener(
523
- self, plugin_name: str, extension: str, callback: Callable, priority: int = 0
528
+ self,
529
+ plugin_name: str,
530
+ extension: str,
531
+ callback: Callable[..., Any],
532
+ priority: int = 0,
524
533
  ) -> None:
525
534
  """Register a file-type handler for the given extension."""
526
535
  # Normalize extension to lowercase
@@ -540,7 +549,7 @@ class PluginManager:
540
549
 
541
550
  # Analysis Tools registration
542
551
  def register_analysis_tool(
543
- self, plugin_name: str, label: str, callback: Callable
552
+ self, plugin_name: str, label: str, callback: Callable[..., Any]
544
553
  ) -> None:
545
554
  """Register a plugin analysis tool with its label and callback."""
546
555
  self.analysis_tools.append(
@@ -548,16 +557,20 @@ class PluginManager:
548
557
  )
549
558
 
550
559
  # State Persistence registration
551
- def register_save_handler(self, plugin_name: str, callback: Callable) -> None:
560
+ def register_save_handler(
561
+ self, plugin_name: str, callback: Callable[..., Any]
562
+ ) -> None:
552
563
  """Register a plugin session-save callback."""
553
564
  self.save_handlers[plugin_name] = callback
554
565
 
555
- def register_load_handler(self, plugin_name: str, callback: Callable) -> None:
566
+ def register_load_handler(
567
+ self, plugin_name: str, callback: Callable[..., Any]
568
+ ) -> None:
556
569
  """Register a plugin session-load callback."""
557
570
  self.load_handlers[plugin_name] = callback
558
571
 
559
572
  def register_3d_style(
560
- self, plugin_name: str, style_name: str, callback: Callable
573
+ self, plugin_name: str, style_name: str, callback: Callable[..., Any]
561
574
  ) -> None:
562
575
  """Register a named custom 3D rendering style."""
563
576
  self.custom_3d_styles[style_name] = {
@@ -566,14 +579,16 @@ class PluginManager:
566
579
  }
567
580
 
568
581
  def register_document_reset_handler(
569
- self, plugin_name: str, callback: Callable
582
+ self, plugin_name: str, callback: Callable[..., Any]
570
583
  ) -> None:
571
584
  """Register callback to be invoked when a new document is created."""
572
585
  self.document_reset_handlers.append(
573
586
  {"plugin": plugin_name, "callback": callback}
574
587
  )
575
588
 
576
- def register_atom_drag_handler(self, plugin_name: str, callback: Callable) -> None:
589
+ def register_atom_drag_handler(
590
+ self, plugin_name: str, callback: Callable[..., Any]
591
+ ) -> None:
577
592
  """Register a handler called during 3D atom/group dragging."""
578
593
  self.atom_drag_handlers.append({"plugin": plugin_name, "callback": callback})
579
594
 
@@ -676,7 +691,7 @@ class PluginManager:
676
691
  self,
677
692
  event_type: str,
678
693
  atom_indices: List[int],
679
- positions: Dict[int, tuple],
694
+ positions: Dict[int, Tuple[float, ...]],
680
695
  ) -> None:
681
696
  """Call all registered atom drag handlers."""
682
697
  for handler in self.atom_drag_handlers:
@@ -75,7 +75,7 @@ class AnalysisWindow(QDialog):
75
75
  total_atoms = len(xyz_atoms)
76
76
  num_heavy_atoms = 0
77
77
 
78
- for symbol, x, y, z in xyz_atoms:
78
+ for symbol, _x, _y, _z in xyz_atoms:
79
79
  atom_counts[symbol] = atom_counts.get(symbol, 0) + 1
80
80
  if symbol != "H": # Non-hydrogen
81
81
  num_heavy_atoms += 1
@@ -154,12 +154,15 @@ class AnalysisWindow(QDialog):
154
154
 
155
155
  # Calculate various properties
156
156
  mol_formula = rdMolDescriptors.CalcMolFormula(self.mol)
157
- mol_wt = Descriptors.MolWt(self.mol)
158
- exact_mw = Descriptors.ExactMolWt(self.mol)
157
+ # Descriptors.MolWt is generated at import time from rdkit's
158
+ # descriptor table, so no stub can declare it; the rest have
159
+ # direct rdMolDescriptors equivalents used elsewhere here.
160
+ mol_wt = Descriptors.MolWt(self.mol) # type: ignore[attr-defined]
161
+ exact_mw = rdMolDescriptors.CalcExactMolWt(self.mol)
159
162
  num_heavy_atoms = self.mol.GetNumHeavyAtoms()
160
163
  num_rings = rdMolDescriptors.CalcNumRings(self.mol)
161
- log_p = Descriptors.MolLogP(self.mol)
162
- tpsa = Descriptors.TPSA(self.mol)
164
+ log_p = rdMolDescriptors.CalcCrippenDescriptors(self.mol)[0]
165
+ tpsa = rdMolDescriptors.CalcTPSA(self.mol)
163
166
  num_h_donors = rdMolDescriptors.CalcNumHBD(self.mol)
164
167
  num_h_acceptors = rdMolDescriptors.CalcNumHBA(self.mol)
165
168
 
@@ -19,7 +19,7 @@ import copy
19
19
  import logging
20
20
  import os
21
21
  from ..utils.suppress_log import suppress_log
22
- from typing import Any, Dict, Optional, Tuple
22
+ from typing import Any, Dict, List, Optional, Tuple
23
23
 
24
24
 
25
25
  import numpy as np
@@ -43,7 +43,7 @@ if TYPE_CHECKING:
43
43
 
44
44
 
45
45
  # --- Class Definition ---
46
- def _serialize_constraints(constraints: list) -> list:
46
+ def _serialize_constraints(constraints: List[Any]) -> List[List[Any]]:
47
47
  """Convert internal constraint tuples to JSON-serializable lists."""
48
48
  result = []
49
49
  for const in constraints:
@@ -54,7 +54,7 @@ def _serialize_constraints(constraints: list) -> list:
54
54
  return result
55
55
 
56
56
 
57
- def _deserialize_constraints(raw: list) -> list:
57
+ def _deserialize_constraints(raw: List[Any]) -> List[Tuple[Any, ...]]:
58
58
  """Convert JSON-loaded constraint lists back to internal tuples."""
59
59
  result = []
60
60
  for const in raw:
@@ -228,7 +228,7 @@ class StateManager:
228
228
  if self.host.view_3d_manager.plotter and not getattr(
229
229
  self.host, "is_restoring_state", False
230
230
  ):
231
- self.host.view_3d_manager.plotter.reset_camera()
231
+ self.host.view_3d_manager.plotter.reset_camera() # type: ignore[call-arg]
232
232
 
233
233
  self.host.ui_manager.enable_3d_features(True)
234
234
  self.host.view_3d_manager.setup_3d_hover()
@@ -481,7 +481,9 @@ class StateManager:
481
481
  json_data["molecular_info"] = {
482
482
  "num_atoms": self.host.view_3d_manager.current_mol.GetNumAtoms(),
483
483
  "num_bonds": self.host.view_3d_manager.current_mol.GetNumBonds(),
484
- "molecular_weight": Descriptors.MolWt(
484
+ # Generated at import time from rdkit's descriptor
485
+ # table, so no stub can declare it.
486
+ "molecular_weight": Descriptors.MolWt( # type: ignore[attr-defined]
485
487
  self.host.view_3d_manager.current_mol
486
488
  ),
487
489
  "formula": rdMolDescriptors.CalcMolFormula(
@@ -620,7 +622,11 @@ class StateManager:
620
622
  mol_base64 = structure_3d.get("mol_binary_base64")
621
623
  if mol_base64:
622
624
  mol_binary = base64.b64decode(mol_base64.encode("ascii"))
623
- self.host.set_current_molecule(Chem.Mol(mol_binary))
625
+ # Chem.Mol accepts a pickled binary block at runtime;
626
+ # the stub only overloads Mol/str.
627
+ self.host.set_current_molecule(
628
+ Chem.Mol(mol_binary) # type: ignore[call-overload]
629
+ )
624
630
  if self.host.view_3d_manager.current_mol:
625
631
  # Set 3D coordinates
626
632
  if self.host.view_3d_manager.current_mol.GetNumConformers() > 0:
@@ -686,7 +692,7 @@ class StateManager:
686
692
  self.host.set_is_2d_editable(True)
687
693
 
688
694
  if self.host.view_3d_manager.plotter:
689
- self.host.view_3d_manager.plotter.reset_camera()
695
+ self.host.view_3d_manager.plotter.reset_camera() # type: ignore[call-arg]
690
696
 
691
697
  # Enable 3D-related UI
692
698
  try:
@@ -11,7 +11,7 @@ DOI: 10.5281/zenodo.17268532
11
11
  """
12
12
 
13
13
  import logging
14
- from typing import TYPE_CHECKING, Any, Optional, Union
14
+ from typing import Any, List, Optional, Union, TYPE_CHECKING
15
15
 
16
16
  import numpy as np
17
17
  from PyQt6.QtCore import Qt, QTimer
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
25
25
  from .main_window import MainWindow
26
26
 
27
27
 
28
- class SelectionList(list):
28
+ class SelectionList(List[int]):
29
29
  """Order-preserving list that compares equal to sets/lists/tuples of same elements."""
30
30
 
31
31
  def __eq__(self, other: object) -> bool: