MoleditPy 3.0.0a7__tar.gz → 3.0.0b1__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 (78) hide show
  1. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/PKG-INFO +1 -1
  2. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/pyproject.toml +1 -1
  3. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/PKG-INFO +1 -1
  4. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/plugins/plugin_manager_window.py +56 -17
  5. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/main_window_init.py +18 -15
  6. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/utils/constants.py +1 -1
  7. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/LICENSE +0 -0
  8. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/README.md +0 -0
  9. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/setup.cfg +0 -0
  10. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/SOURCES.txt +0 -0
  11. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/dependency_links.txt +0 -0
  12. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/entry_points.txt +0 -0
  13. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/requires.txt +0 -0
  14. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/MoleditPy.egg-info/top_level.txt +0 -0
  15. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/__init__.py +0 -0
  16. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/__main__.py +0 -0
  17. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/assets/file_icon.ico +0 -0
  18. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/assets/icon.icns +0 -0
  19. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/assets/icon.ico +0 -0
  20. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/assets/icon.png +0 -0
  21. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/core/__init__.py +0 -0
  22. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/core/mol_geometry.py +0 -0
  23. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/core/molecular_data.py +0 -0
  24. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/main.py +0 -0
  25. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/plugins/__init__.py +0 -0
  26. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/plugins/plugin_interface.py +0 -0
  27. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/plugins/plugin_manager.py +0 -0
  28. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/__init__.py +0 -0
  29. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/about_dialog.py +0 -0
  30. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/align_plane_dialog.py +0 -0
  31. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/alignment_dialog.py +0 -0
  32. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/analysis_window.py +0 -0
  33. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/angle_dialog.py +0 -0
  34. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/app_state.py +0 -0
  35. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/atom_item.py +0 -0
  36. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/base_picking_dialog.py +0 -0
  37. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/bond_item.py +0 -0
  38. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/bond_length_dialog.py +0 -0
  39. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/calculation_worker.py +0 -0
  40. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/color_settings_dialog.py +0 -0
  41. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/compute_logic.py +0 -0
  42. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/constrained_optimization_dialog.py +0 -0
  43. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/custom_interactor_style.py +0 -0
  44. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/custom_qt_interactor.py +0 -0
  45. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/dialog_3d_picking_mixin.py +0 -0
  46. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/dialog_logic.py +0 -0
  47. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/dihedral_dialog.py +0 -0
  48. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/edit_3d_logic.py +0 -0
  49. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/edit_actions_logic.py +0 -0
  50. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/export_logic.py +0 -0
  51. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/geometry_base_dialog.py +0 -0
  52. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/io_logic.py +0 -0
  53. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/main_window.py +0 -0
  54. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/mirror_dialog.py +0 -0
  55. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/molecular_scene_handler.py +0 -0
  56. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/molecule_scene.py +0 -0
  57. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/move_group_dialog.py +0 -0
  58. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/periodic_table_dialog.py +0 -0
  59. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/planarize_dialog.py +0 -0
  60. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_dialog.py +0 -0
  61. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_tabs/__init__.py +0 -0
  62. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_tabs/settings_2d_tab.py +0 -0
  63. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_tabs/settings_3d_tabs.py +0 -0
  64. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_tabs/settings_other_tab.py +0 -0
  65. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/settings_tabs/settings_tab_base.py +0 -0
  66. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/sip_isdeleted_safe.py +0 -0
  67. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/string_importers.py +0 -0
  68. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/template_preview_item.py +0 -0
  69. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/template_preview_view.py +0 -0
  70. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/translation_dialog.py +0 -0
  71. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/ui_manager.py +0 -0
  72. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/user_template_dialog.py +0 -0
  73. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/view_3d_logic.py +0 -0
  74. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/ui/zoomable_view.py +0 -0
  75. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/utils/__init__.py +0 -0
  76. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/utils/default_settings.py +0 -0
  77. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/utils/sip_isdeleted_safe.py +0 -0
  78. {moleditpy-3.0.0a7 → moleditpy-3.0.0b1}/src/moleditpy/utils/system_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy
3
- Version: 3.0.0a7
3
+ Version: 3.0.0b1
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
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "MoleditPy"
7
7
 
8
- version = "3.0.0a7"
8
+ version = "3.0.0b1"
9
9
 
10
10
  license = {file = "LICENSE"}
11
11
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: MoleditPy
3
- Version: 3.0.0a7
3
+ Version: 3.0.0b1
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
@@ -10,8 +10,9 @@ Repo: https://github.com/HiroYokoyama/python_molecular_editor
10
10
  DOI: 10.5281/zenodo.17268532
11
11
  """
12
12
 
13
- import os
14
- import shutil
13
+ import os
14
+ import shutil
15
+ import hashlib
15
16
 
16
17
  from PyQt6.QtCore import Qt, QUrl
17
18
  from PyQt6.QtGui import QDesktopServices, QDragEnterEvent, QDropEvent
@@ -257,9 +258,10 @@ class PluginManagerWindow(QDialog):
257
258
  is_valid = True
258
259
  is_folder = True
259
260
 
260
- if is_valid:
261
- # Extract info and confirm
262
- info = {
261
+ if is_valid:
262
+ sha256_value = self._compute_sha256(file_path)
263
+ # Extract info and confirm
264
+ info = {
263
265
  "name": os.path.basename(file_path),
264
266
  "version": "Unknown",
265
267
  "author": "Unknown",
@@ -279,14 +281,15 @@ class PluginManagerWindow(QDialog):
279
281
  elif file_path.endswith(".py"):
280
282
  info = self.plugin_manager.get_plugin_info_safe(file_path)
281
283
 
282
- msg = (
283
- f"Do you want to install this plugin?\n\n"
284
- f"Name: {info['name']}\n"
285
- f"Author: {info['author']}\n"
286
- f"Version: {info['version']}\n"
287
- f"Description: {info['description']}\n\n"
288
- f"File: {os.path.basename(file_path)}"
289
- )
284
+ msg = (
285
+ f"Do you want to install this plugin?\n\n"
286
+ f"Name: {info['name']}\n"
287
+ f"Author: {info['author']}\n"
288
+ f"Version: {info['version']}\n"
289
+ f"Description: {info['description']}\n\n"
290
+ f"File: {os.path.basename(file_path)}\n"
291
+ f"SHA-256: {sha256_value}"
292
+ )
290
293
 
291
294
  reply = QMessageBox.question(
292
295
  self,
@@ -307,7 +310,43 @@ class PluginManagerWindow(QDialog):
307
310
  summary = ""
308
311
  if files_installed:
309
312
  summary += "Installed:\n" + "\n".join(files_installed) + "\n\n"
310
- if errors:
311
- summary += "Errors:\n" + "\n".join(errors)
312
-
313
- QMessageBox.information(self, "Plugin Installation", summary)
313
+ if errors:
314
+ summary += "Errors:\n" + "\n".join(errors)
315
+
316
+ QMessageBox.information(self, "Plugin Installation", summary)
317
+
318
+ def _compute_sha256(self, path):
319
+ if os.path.isfile(path):
320
+ return self._sha256_for_file(path)
321
+ if os.path.isdir(path):
322
+ return self._sha256_for_directory(path)
323
+ return "N/A"
324
+
325
+ def _sha256_for_file(self, path):
326
+ hasher = hashlib.sha256()
327
+ try:
328
+ with open(path, "rb") as f:
329
+ for chunk in iter(lambda: f.read(8192), b""):
330
+ hasher.update(chunk)
331
+ return hasher.hexdigest()
332
+ except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
333
+ return "N/A"
334
+
335
+ def _sha256_for_directory(self, dir_path):
336
+ hasher = hashlib.sha256()
337
+ try:
338
+ root = os.path.abspath(dir_path)
339
+ for current_root, _dirs, files in os.walk(root):
340
+ rel_root = os.path.relpath(current_root, root)
341
+ for filename in sorted(files):
342
+ file_path = os.path.join(current_root, filename)
343
+ rel_path = os.path.normpath(os.path.join(rel_root, filename))
344
+ hasher.update(rel_path.encode("utf-8", errors="replace"))
345
+ hasher.update(b"\0")
346
+ with open(file_path, "rb") as f:
347
+ for chunk in iter(lambda: f.read(8192), b""):
348
+ hasher.update(chunk)
349
+ hasher.update(b"\0")
350
+ return hasher.hexdigest()
351
+ except (AttributeError, OSError, RuntimeError, ValueError, TypeError):
352
+ return "N/A"
@@ -840,17 +840,20 @@ class MainInitManager:
840
840
  a.setData(PLUGIN_ACTION_TAG)
841
841
  menu.addAction(a)
842
842
 
843
- def _integrate_plugin_file_openers(self):
844
- """Add plugin-provided file openers to the import menu."""
845
- if (
846
- not hasattr(self.host, "import_menu")
847
- or not self.host.plugin_manager.file_openers
848
- ):
849
- return
850
-
851
- PLUGIN_ACTION_TAG = "plugin_managed"
852
- sep = self.import_menu.addSeparator()
853
- sep.setData(PLUGIN_ACTION_TAG)
843
+ def _integrate_plugin_file_openers(self):
844
+ """Add plugin-provided file openers to the import menu."""
845
+ if not self.host.plugin_manager.file_openers:
846
+ return
847
+
848
+ import_menu = getattr(self, "import_menu", None) or getattr(
849
+ self.host, "import_menu", None
850
+ )
851
+ if import_menu is None:
852
+ return
853
+
854
+ PLUGIN_ACTION_TAG = "plugin_managed"
855
+ sep = import_menu.addSeparator()
856
+ sep.setData(PLUGIN_ACTION_TAG)
854
857
 
855
858
  plugin_map = {}
856
859
  for ext, openers in self.host.plugin_manager.file_openers.items():
@@ -884,10 +887,10 @@ class MainInitManager:
884
887
 
885
888
  return _cb
886
889
 
887
- a = QAction(f"Import {ext_str} ({p_name})...", self.host)
888
- a.triggered.connect(make_cb(ext_map, filter_str, p_name))
889
- a.setData(PLUGIN_ACTION_TAG)
890
- self.import_menu.addAction(a)
890
+ a = QAction(f"Import {ext_str} ({p_name})...", self.host)
891
+ a.triggered.connect(make_cb(ext_map, filter_str, p_name))
892
+ a.setData(PLUGIN_ACTION_TAG)
893
+ import_menu.addAction(a)
891
894
 
892
895
  def _integrate_plugin_analysis_tools(self):
893
896
  """Add plugin-provided analysis tools to the analysis menu."""
@@ -16,7 +16,7 @@ from PyQt6.QtGui import QColor, QFont
16
16
  from rdkit import Chem
17
17
 
18
18
  # Version
19
- VERSION = "3.0.0a7"
19
+ VERSION = "3.0.0b1"
20
20
 
21
21
  ATOM_RADIUS = 18
22
22
  BOND_OFFSET = 3.5
File without changes
File without changes
File without changes