leaf-framework 0.7.0__tar.gz → 0.9.0__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 (104) hide show
  1. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/PKG-INFO +1 -1
  2. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/desktop_launcher.py +45 -5
  3. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/pyproject.toml +1 -1
  4. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/LICENSE +0 -0
  5. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/README.md +0 -0
  6. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/__init__.py +0 -0
  7. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/__init__.py +0 -0
  8. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/core_adapters/__init__.py +0 -0
  9. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/core_adapters/continuous_experiment_adapter.py +0 -0
  10. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/core_adapters/discrete_experiment_adapter.py +0 -0
  11. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/core_adapters/upload_adapter.py +0 -0
  12. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/adapters/equipment_adapter.py +0 -0
  13. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/config/configuration.yaml +0 -0
  14. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/data/marketplace.yaml +0 -0
  15. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/error_handler/__init__.py +0 -0
  16. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/error_handler/error_holder.py +0 -0
  17. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/error_handler/exceptions.py +0 -0
  18. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/measurement_handler/__init__.py +0 -0
  19. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/measurement_handler/handler.py +0 -0
  20. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/measurement_handler/measurements.yaml +0 -0
  21. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/measurement_handler/terms.py +0 -0
  22. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/.gitkeep +0 -0
  23. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/__init__.py +0 -0
  24. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/__init__.py +0 -0
  25. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/ble_watcher.py +0 -0
  26. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/db_watcher.py +0 -0
  27. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/event_watcher.py +0 -0
  28. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/external_api_watcher.py +0 -0
  29. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/external_event_watcher.py +0 -0
  30. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/file_watcher.py +0 -0
  31. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/http_watcher.py +0 -0
  32. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/modbus_watcher.py +0 -0
  33. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/mqtt_external_event_watcher.py +0 -0
  34. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/mqtt_watcher.py +0 -0
  35. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/opc_watcher.py +0 -0
  36. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/polling_watcher.py +0 -0
  37. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/input_modules/simple_watcher.py +0 -0
  38. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/__init__.py +0 -0
  39. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/carbon_dioxide.py +0 -0
  40. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/dissolved_oxygen.py +0 -0
  41. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/fluorescence.py +0 -0
  42. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/measurement_module.py +0 -0
  43. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/optical_density.py +0 -0
  44. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/ph.py +0 -0
  45. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/measurement_modules/temperature.py +0 -0
  46. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/__init__.py +0 -0
  47. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/file.py +0 -0
  48. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/keydb.py +0 -0
  49. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/mqtt.py +0 -0
  50. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/output_module.py +0 -0
  51. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/sql.py +0 -0
  52. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/output_modules/topic_store.py +0 -0
  53. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/__init__.py +0 -0
  54. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/control.py +0 -0
  55. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/error.py +0 -0
  56. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/external_event_phase.py +0 -0
  57. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/initialisation.py +0 -0
  58. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/measure.py +0 -0
  59. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/phase.py +0 -0
  60. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/start.py +0 -0
  61. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/phase_modules/stop.py +0 -0
  62. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/__init__.py +0 -0
  63. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/continous_module.py +0 -0
  64. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/discrete_module.py +0 -0
  65. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/external_event_process.py +0 -0
  66. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/process_module.py +0 -0
  67. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/modules/process_modules/upload_module.py +0 -0
  68. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/__init__.py +0 -0
  69. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/abstract_leaf.py +0 -0
  70. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/equipment_actions.yaml +0 -0
  71. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/equipment_data.yaml +0 -0
  72. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/metadata.py +0 -0
  73. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/py.typed +0 -0
  74. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/register/topic_utilities.py +0 -0
  75. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/registry/discovery.py +0 -0
  76. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/registry/loader.py +0 -0
  77. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/registry/registry.py +0 -0
  78. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/registry/utils.py +0 -0
  79. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/start.py +0 -0
  80. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/__init__.py +0 -0
  81. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/adapter_ui_extension.py +0 -0
  82. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/components/__init__.py +0 -0
  83. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/components/header.py +0 -0
  84. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/constants.py +0 -0
  85. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/images/icon.icns +0 -0
  86. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/images/icon.ico +0 -0
  87. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/images/icon.svg +0 -0
  88. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/interface.py +0 -0
  89. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/markdown/configuration_help.md +0 -0
  90. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/markdown/documentation_main.md +0 -0
  91. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/markdown/documentation_protips.md +0 -0
  92. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/scripts.js +0 -0
  93. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/styles.css +0 -0
  94. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/__init__.py +0 -0
  95. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/adapters.py +0 -0
  96. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/configuration.py +0 -0
  97. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/documentation.py +0 -0
  98. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/logs.py +0 -0
  99. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/tabs/monitoring.py +0 -0
  100. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/ui/utils.py +0 -0
  101. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/utility/config_utils.py +0 -0
  102. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/utility/logger/__init__.py +0 -0
  103. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/utility/logger/logger_utils.py +0 -0
  104. {leaf_framework-0.7.0 → leaf_framework-0.9.0}/leaf/utility/running_utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: leaf-framework
3
- Version: 0.7.0
3
+ Version: 0.9.0
4
4
  Summary: Lightweight Adapter Framework (LEAF)
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -1,6 +1,7 @@
1
1
  """Desktop GUI launcher for LEAF - Simple control panel for users."""
2
2
 
3
3
  import os
4
+ import subprocess
4
5
  import sys
5
6
  import threading
6
7
  import webbrowser
@@ -45,12 +46,19 @@ def is_desktop_environment() -> bool:
45
46
  if not os.environ.get("DISPLAY"):
46
47
  return False
47
48
 
48
- # Try to create a test window to verify tkinter actually works
49
+ # Verify tkinter actually works by creating a test window -- in a
50
+ # *subprocess*, not in-process. tkinter only supports one Tk() root per
51
+ # process; creating-and-destroying a throwaway root here would leave the
52
+ # *real* root (created later by LeafDesktopLauncher, in this same
53
+ # process) in a broken state on macOS: it still registers a Dock icon
54
+ # but the window itself never becomes visible or responds to input.
49
55
  try:
50
- root = tk.Tk()
51
- root.withdraw()
52
- root.destroy()
53
- return True
56
+ result = subprocess.run(
57
+ [sys.executable, "-c", "import tkinter; r = tkinter.Tk(); r.withdraw(); r.destroy()"],
58
+ capture_output=True,
59
+ timeout=10,
60
+ )
61
+ return result.returncode == 0
54
62
  except Exception as e:
55
63
  logger.debug(f"Desktop environment check failed: {e}")
56
64
  return False
@@ -296,10 +304,42 @@ class LeafDesktopLauncher:
296
304
  logger.info("User closed desktop launcher window")
297
305
  self.stop_leaf()
298
306
 
307
+ def _bring_to_front(self):
308
+ """Force the window to the foreground and give it real input focus.
309
+
310
+ Needed when this process was exec'd into from an already-running
311
+ signed .app (see packaging/launcher/bootstrap.py) rather than being
312
+ launched directly as its own bundled app: Tk's window then draws
313
+ fine but doesn't reliably become the active/frontmost app, so it
314
+ renders but silently ignores clicks.
315
+ """
316
+ self.root.lift()
317
+ self.root.attributes("-topmost", True)
318
+ self.root.after_idle(self.root.attributes, "-topmost", False)
319
+ self.root.focus_force()
320
+ if sys.platform == "darwin":
321
+ try:
322
+ import subprocess
323
+
324
+ subprocess.run(
325
+ [
326
+ "osascript",
327
+ "-e",
328
+ 'tell application "System Events" to set frontmost of '
329
+ f"(first process whose unix id is {os.getpid()}) to true",
330
+ ],
331
+ check=False,
332
+ timeout=2,
333
+ )
334
+ except Exception as e:
335
+ logger.debug(f"Could not force-activate window via osascript: {e}")
336
+
299
337
  def run(self):
300
338
  """Run the desktop launcher main loop."""
301
339
  logger.info("Starting desktop launcher GUI")
302
340
  try:
341
+ self._bring_to_front()
342
+
303
343
  # Auto-open browser on startup after a short delay
304
344
  self.root.after(1500, self.open_browser)
305
345
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "leaf-framework"
3
- version = "0.7.0"
3
+ version = "0.9.0"
4
4
  description = "Lightweight Adapter Framework (LEAF)"
5
5
  authors = [
6
6
  "Matthew Crowther <nmc215@ncl.ac.uk>",
File without changes
File without changes