leaf-framework 0.9.3__tar.gz → 0.9.5__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.
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/PKG-INFO +1 -1
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/desktop_launcher.py +40 -5
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/pyproject.toml +1 -1
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/LICENSE +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/README.md +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/core_adapters/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/core_adapters/continuous_experiment_adapter.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/core_adapters/discrete_experiment_adapter.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/core_adapters/upload_adapter.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/adapters/equipment_adapter.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/config/configuration.yaml +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/data/marketplace.yaml +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/error_handler/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/error_handler/error_holder.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/error_handler/exceptions.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/measurement_handler/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/measurement_handler/handler.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/measurement_handler/measurements.yaml +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/measurement_handler/terms.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/.gitkeep +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/ble_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/db_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/event_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/external_api_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/external_event_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/file_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/http_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/modbus_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/mqtt_external_event_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/mqtt_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/opc_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/polling_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/simple_watcher.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/carbon_dioxide.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/dissolved_oxygen.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/fluorescence.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/measurement_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/optical_density.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/ph.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/temperature.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/file.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/keydb.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/mqtt.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/output_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/sql.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/output_modules/topic_store.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/control.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/error.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/external_event_phase.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/initialisation.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/measure.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/phase.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/start.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/stop.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/continous_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/discrete_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/external_event_process.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/process_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/upload_module.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/abstract_leaf.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/equipment_actions.yaml +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/equipment_data.yaml +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/metadata.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/py.typed +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/register/topic_utilities.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/registry/discovery.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/registry/loader.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/registry/registry.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/registry/utils.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/start.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/adapter_ui_extension.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/components/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/components/header.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/constants.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/images/icon.icns +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/images/icon.ico +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/images/icon.svg +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/interface.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/markdown/configuration_help.md +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/markdown/documentation_main.md +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/markdown/documentation_protips.md +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/scripts.js +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/styles.css +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/adapters.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/configuration.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/documentation.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/logs.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/tabs/monitoring.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/ui/utils.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/utility/config_utils.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/utility/logger/__init__.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/utility/logger/logger_utils.py +0 -0
- {leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/utility/running_utilities.py +0 -0
|
@@ -23,6 +23,28 @@ except ImportError:
|
|
|
23
23
|
logger.warning("tkinter not available - desktop GUI will not be available")
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def _init_x11_threads() -> None:
|
|
27
|
+
"""Tell Xlib this process is multi-threaded, before it ever touches X11.
|
|
28
|
+
|
|
29
|
+
LEAF always has other threads running by the time this GUI starts (the
|
|
30
|
+
NiceGUI web server thread, adapter/simulation threads -- see start.py),
|
|
31
|
+
even though none of them are meant to touch Tk/X11 directly. Xlib is
|
|
32
|
+
documented as requiring XInitThreads() to be called before its first
|
|
33
|
+
use in any process that is multi-threaded at all, regardless of which
|
|
34
|
+
thread actually issues X calls; skipping it is exactly what produces
|
|
35
|
+
"Unknown sequence number ... XInitThreads has not been called" xcb
|
|
36
|
+
aborts on Linux. No equivalent exists on macOS (Cocoa) or Windows.
|
|
37
|
+
"""
|
|
38
|
+
if not sys.platform.startswith("linux"):
|
|
39
|
+
return
|
|
40
|
+
try:
|
|
41
|
+
import ctypes
|
|
42
|
+
|
|
43
|
+
ctypes.CDLL("libX11.so.6").XInitThreads()
|
|
44
|
+
except Exception as e:
|
|
45
|
+
logger.debug(f"Could not call XInitThreads: {e}")
|
|
46
|
+
|
|
47
|
+
|
|
26
48
|
def is_desktop_environment() -> bool:
|
|
27
49
|
"""
|
|
28
50
|
Detect if we're running in a desktop environment.
|
|
@@ -82,6 +104,7 @@ class LeafDesktopLauncher:
|
|
|
82
104
|
self.is_running = True
|
|
83
105
|
|
|
84
106
|
# Create main window
|
|
107
|
+
_init_x11_threads()
|
|
85
108
|
self.root = tk.Tk()
|
|
86
109
|
self.root.title("LEAF - Lightweight Equipment Adapter Framework")
|
|
87
110
|
self.root.geometry("500x350")
|
|
@@ -281,6 +304,7 @@ class LeafDesktopLauncher:
|
|
|
281
304
|
|
|
282
305
|
# Call the stop callback in a separate thread
|
|
283
306
|
if self.on_stop_callback:
|
|
307
|
+
stop_finished = threading.Event()
|
|
284
308
|
|
|
285
309
|
def stop_thread():
|
|
286
310
|
try:
|
|
@@ -288,13 +312,24 @@ class LeafDesktopLauncher:
|
|
|
288
312
|
except Exception as e:
|
|
289
313
|
logger.error(f"Error in stop callback: {e}")
|
|
290
314
|
finally:
|
|
291
|
-
|
|
292
|
-
try:
|
|
293
|
-
self.root.after(1000, self.root.destroy)
|
|
294
|
-
except Exception:
|
|
295
|
-
pass
|
|
315
|
+
stop_finished.set()
|
|
296
316
|
|
|
297
317
|
threading.Thread(target=stop_thread, daemon=True).start()
|
|
318
|
+
|
|
319
|
+
# Tk/Tcl calls (root.after, root.destroy) must only ever happen
|
|
320
|
+
# on the main thread that's running mainloop() -- on Linux,
|
|
321
|
+
# Xlib can abort the whole process ("XInitThreads has not been
|
|
322
|
+
# called") if a background thread issues X11 calls concurrently
|
|
323
|
+
# with it. Polling here (itself scheduled via root.after, so it
|
|
324
|
+
# always runs on the main thread) instead of destroying directly
|
|
325
|
+
# from stop_thread keeps every Tk call on that one thread.
|
|
326
|
+
def wait_and_destroy():
|
|
327
|
+
if stop_finished.is_set():
|
|
328
|
+
self.root.destroy()
|
|
329
|
+
else:
|
|
330
|
+
self.root.after(100, wait_and_destroy)
|
|
331
|
+
|
|
332
|
+
self.root.after(1000, wait_and_destroy)
|
|
298
333
|
else:
|
|
299
334
|
# If no callback, just close
|
|
300
335
|
self.root.after(500, self.root.destroy)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/external_api_watcher.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/input_modules/external_event_watcher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/carbon_dioxide.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/dissolved_oxygen.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/fluorescence.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/measurement_module.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/optical_density.py
RENAMED
|
File without changes
|
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/measurement_modules/temperature.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/phase_modules/external_event_phase.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/continous_module.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/discrete_module.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/external_event_process.py
RENAMED
|
File without changes
|
{leaf_framework-0.9.3 → leaf_framework-0.9.5}/leaf/modules/process_modules/process_module.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|