mmrelay 1.2.0__tar.gz → 1.2.2__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.

Potentially problematic release.


This version of mmrelay might be problematic. Click here for more details.

Files changed (117) hide show
  1. {mmrelay-1.2.0/src/mmrelay.egg-info → mmrelay-1.2.2}/PKG-INFO +11 -11
  2. {mmrelay-1.2.0 → mmrelay-1.2.2}/README.md +6 -6
  3. {mmrelay-1.2.0 → mmrelay-1.2.2}/requirements.txt +8 -8
  4. {mmrelay-1.2.0 → mmrelay-1.2.2}/setup.py +5 -5
  5. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/__init__.py +1 -1
  6. mmrelay-1.2.2/src/mmrelay/__main__.py +29 -0
  7. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/cli.py +735 -135
  8. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/cli_utils.py +59 -9
  9. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/config.py +198 -71
  10. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/app.py +2 -2
  11. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/db_utils.py +73 -26
  12. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/e2ee_utils.py +6 -3
  13. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/log_utils.py +16 -5
  14. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/main.py +41 -38
  15. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/matrix_utils.py +1069 -293
  16. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/meshtastic_utils.py +350 -206
  17. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/message_queue.py +212 -62
  18. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugin_loader.py +634 -205
  19. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/mesh_relay_plugin.py +43 -38
  20. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/weather_plugin.py +11 -12
  21. mmrelay-1.2.2/src/mmrelay/runtime_utils.py +35 -0
  22. mmrelay-1.2.2/src/mmrelay/setup_utils.py +828 -0
  23. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/tools/mmrelay.service +2 -1
  24. mmrelay-1.2.2/src/mmrelay/tools/sample-docker-compose-prebuilt.yaml +19 -0
  25. mmrelay-1.2.2/src/mmrelay/tools/sample-docker-compose.yaml +19 -0
  26. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/tools/sample_config.yaml +14 -13
  27. mmrelay-1.2.2/src/mmrelay/windows_utils.py +349 -0
  28. {mmrelay-1.2.0 → mmrelay-1.2.2/src/mmrelay.egg-info}/PKG-INFO +11 -11
  29. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay.egg-info/SOURCES.txt +13 -1
  30. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay.egg-info/requires.txt +4 -4
  31. mmrelay-1.2.2/tests/test_auth_flow_fixes.py +159 -0
  32. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_base_plugin.py +3 -0
  33. mmrelay-1.2.2/tests/test_cli.py +3626 -0
  34. mmrelay-1.2.2/tests/test_cli_diagnose.py +329 -0
  35. mmrelay-1.2.2/tests/test_cli_windows_integration.py +335 -0
  36. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_config_checker.py +220 -4
  37. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_db_utils_edge_cases.py +2 -2
  38. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_debug_plugin.py +3 -0
  39. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_drop_plugin.py +3 -0
  40. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_e2ee_unified.py +89 -41
  41. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_error_boundaries.py +13 -7
  42. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_health_plugin.py +3 -0
  43. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_help_plugin.py +3 -0
  44. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_log_utils.py +2 -2
  45. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_main.py +21 -23
  46. mmrelay-1.2.2/tests/test_main_entry_point.py +239 -0
  47. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_map_plugin.py +5 -1
  48. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_matrix_utils.py +1266 -428
  49. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_matrix_utils_edge_cases.py +19 -18
  50. mmrelay-1.2.2/tests/test_matrix_utils_error_handling.py +437 -0
  51. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_mesh_relay_plugin.py +16 -4
  52. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_meshtastic_utils.py +8 -5
  53. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_meshtastic_utils_edge_cases.py +254 -28
  54. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_message_queue.py +71 -45
  55. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_message_queue_edge_cases.py +9 -28
  56. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_network_reliability.py +8 -6
  57. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_nodes_plugin.py +3 -0
  58. mmrelay-1.2.2/tests/test_patch_coverage_improvements.py +204 -0
  59. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_performance_stress.py +60 -19
  60. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_ping_plugin.py +3 -0
  61. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_plugin_loader.py +175 -131
  62. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_plugin_loader_edge_cases.py +11 -11
  63. mmrelay-1.2.2/tests/test_setup_utils.py +1191 -0
  64. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_setup_utils_edge_cases.py +82 -33
  65. mmrelay-1.2.2/tests/test_setup_utils_execstart_improvements.py +94 -0
  66. mmrelay-1.2.2/tests/test_setup_utils_systemctl.py +288 -0
  67. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_telemetry_plugin.py +3 -0
  68. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_weather_plugin.py +3 -0
  69. mmrelay-1.2.2/tests/test_windows_utils.py +256 -0
  70. mmrelay-1.2.0/src/mmrelay/setup_utils.py +0 -633
  71. mmrelay-1.2.0/src/mmrelay/tools/sample-docker-compose-prebuilt.yaml +0 -80
  72. mmrelay-1.2.0/src/mmrelay/tools/sample-docker-compose.yaml +0 -65
  73. mmrelay-1.2.0/tests/test_cli.py +0 -1295
  74. mmrelay-1.2.0/tests/test_setup_utils.py +0 -489
  75. {mmrelay-1.2.0 → mmrelay-1.2.2}/LICENSE +0 -0
  76. {mmrelay-1.2.0 → mmrelay-1.2.2}/MANIFEST.in +0 -0
  77. {mmrelay-1.2.0 → mmrelay-1.2.2}/pyproject.toml +0 -0
  78. {mmrelay-1.2.0 → mmrelay-1.2.2}/setup.cfg +0 -0
  79. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/__init__.py +0 -0
  80. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/config.py +0 -0
  81. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/database.py +0 -0
  82. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/formats.py +0 -0
  83. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/messages.py +0 -0
  84. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/network.py +0 -0
  85. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/constants/queue.py +0 -0
  86. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/__init__.py +0 -0
  87. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/base_plugin.py +0 -0
  88. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/debug_plugin.py +0 -0
  89. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/drop_plugin.py +0 -0
  90. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/health_plugin.py +0 -0
  91. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/help_plugin.py +0 -0
  92. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/map_plugin.py +0 -0
  93. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/nodes_plugin.py +0 -0
  94. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/ping_plugin.py +0 -0
  95. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/plugins/telemetry_plugin.py +0 -0
  96. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/tools/__init__.py +0 -0
  97. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay/tools/sample.env +0 -0
  98. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay.egg-info/dependency_links.txt +0 -0
  99. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay.egg-info/entry_points.txt +0 -0
  100. {mmrelay-1.2.0 → mmrelay-1.2.2}/src/mmrelay.egg-info/top_level.txt +0 -0
  101. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_async_patterns.py +0 -0
  102. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_cli_edge_cases.py +0 -0
  103. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_cli_utils.py +0 -0
  104. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_config.py +0 -0
  105. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_config_edge_cases.py +0 -0
  106. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_constants.py +0 -0
  107. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_core_utils_coverage.py +0 -0
  108. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_db_utils.py +0 -0
  109. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_e2ee_encryption.py +0 -0
  110. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_e2ee_integration.py +0 -0
  111. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_e2ee_runner.py +0 -0
  112. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_imports.py +0 -0
  113. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_integration_scenarios.py +0 -0
  114. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_meshtastic_broadcast_enabled.py +0 -0
  115. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_prefix_customization.py +0 -0
  116. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_runtime_no_errors.py +0 -0
  117. {mmrelay-1.2.0 → mmrelay-1.2.2}/tests/test_tools_init.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mmrelay
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Bridge between Meshtastic mesh networks and Matrix chat rooms
5
5
  Home-page: https://github.com/jeremiah-k/meshtastic-matrix-relay
6
6
  Author: Geoff Whittington, Jeremiah K., and contributors
@@ -22,16 +22,16 @@ Requires-Dist: meshtastic>=2.6.4
22
22
  Requires-Dist: Pillow==11.3.0
23
23
  Requires-Dist: matrix-nio==0.25.2
24
24
  Requires-Dist: matplotlib==3.10.1
25
- Requires-Dist: requests==2.32.4
26
- Requires-Dist: markdown==3.8.2
25
+ Requires-Dist: requests==2.32.5
26
+ Requires-Dist: markdown==3.9
27
27
  Requires-Dist: bleach==6.2.0
28
28
  Requires-Dist: haversine==2.9.0
29
29
  Requires-Dist: schedule==1.2.2
30
- Requires-Dist: platformdirs==4.3.8
30
+ Requires-Dist: platformdirs==4.4.0
31
31
  Requires-Dist: py-staticmaps>=0.4.0
32
32
  Requires-Dist: psutil>=5.8.0
33
33
  Requires-Dist: rich==14.1.0
34
- Requires-Dist: setuptools==80.9.0
34
+ Requires-Dist: setuptools>=80.9.0
35
35
  Provides-Extra: e2e
36
36
  Requires-Dist: matrix-nio[e2e]==0.25.2; extra == "e2e"
37
37
  Requires-Dist: python-olm; extra == "e2e"
@@ -48,7 +48,7 @@ Dynamic: requires-dist
48
48
  Dynamic: requires-python
49
49
  Dynamic: summary
50
50
 
51
- # M<>M Relay
51
+ # MMRelay
52
52
 
53
53
  ## (Meshtastic <=> Matrix Relay)
54
54
 
@@ -69,22 +69,22 @@ A powerful and easy-to-use relay between Meshtastic devices and Matrix chat room
69
69
  - ✨️ _Native Docker support_ ✨️
70
70
  - 🔐 **Matrix End-to-End Encryption (E2EE) support** 🔐 **NEW in v1.2!**
71
71
 
72
- **MMRelay v1.2** introduces full **Matrix End-to-End Encryption** support for secure communication in encrypted rooms. Messages are automatically encrypted/decrypted when communicating with encrypted Matrix rooms, with simple setup using `mmrelay auth login` or automatic credentials creation from config.yaml.
72
+ **MMRelay v1.2** introduces **Matrix End-to-End Encryption** support for secure communication in encrypted rooms. Messages are automatically encrypted/decrypted when communicating with encrypted Matrix rooms, with simple setup using `mmrelay auth login` or automatic credentials creation from config.yaml.
73
73
 
74
74
  ## Documentation
75
75
 
76
- Visit our [Wiki](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki) for comprehensive guides and information.
77
-
78
76
  MMRelay supports multiple deployment methods including Docker, pip installation, and standalone executables. For complete setup instructions and all deployment options, see:
79
77
 
80
78
  - [Installation Instructions](docs/INSTRUCTIONS.md) - Setup and configuration guide
81
79
  - [Docker Guide](docs/DOCKER.md) - Docker deployment methods
80
+ - [What's New in v1.2](docs/WHATS_NEW_1.2.md) - New features and improvements
81
+ - [E2EE Setup Guide](docs/E2EE.md) - Matrix End-to-End Encryption configuration
82
82
 
83
83
  ---
84
84
 
85
85
  ## Plugins
86
86
 
87
- M<>M Relay supports plugins for extending its functionality, enabling customization and enhancement of the relay to suit specific needs.
87
+ MMRelay supports plugins for extending its functionality, enabling customization and enhancement of the relay to suit specific needs.
88
88
 
89
89
  ### Core Plugins
90
90
 
@@ -133,7 +133,7 @@ Plugins make it easy to extend functionality without modifying the core program.
133
133
 
134
134
  ## Getting Started with Matrix
135
135
 
136
- See our Wiki page [Getting Started With Matrix & MM Relay](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki/Getting-Started-With-Matrix-&-MM-Relay).
136
+ See our Wiki page [Getting Started With Matrix & MMRelay](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki/Getting-Started-With-Matrix-&-MM-Relay).
137
137
 
138
138
  ---
139
139
 
@@ -1,4 +1,4 @@
1
- # M<>M Relay
1
+ # MMRelay
2
2
 
3
3
  ## (Meshtastic <=> Matrix Relay)
4
4
 
@@ -19,22 +19,22 @@ A powerful and easy-to-use relay between Meshtastic devices and Matrix chat room
19
19
  - ✨️ _Native Docker support_ ✨️
20
20
  - 🔐 **Matrix End-to-End Encryption (E2EE) support** 🔐 **NEW in v1.2!**
21
21
 
22
- **MMRelay v1.2** introduces full **Matrix End-to-End Encryption** support for secure communication in encrypted rooms. Messages are automatically encrypted/decrypted when communicating with encrypted Matrix rooms, with simple setup using `mmrelay auth login` or automatic credentials creation from config.yaml.
22
+ **MMRelay v1.2** introduces **Matrix End-to-End Encryption** support for secure communication in encrypted rooms. Messages are automatically encrypted/decrypted when communicating with encrypted Matrix rooms, with simple setup using `mmrelay auth login` or automatic credentials creation from config.yaml.
23
23
 
24
24
  ## Documentation
25
25
 
26
- Visit our [Wiki](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki) for comprehensive guides and information.
27
-
28
26
  MMRelay supports multiple deployment methods including Docker, pip installation, and standalone executables. For complete setup instructions and all deployment options, see:
29
27
 
30
28
  - [Installation Instructions](docs/INSTRUCTIONS.md) - Setup and configuration guide
31
29
  - [Docker Guide](docs/DOCKER.md) - Docker deployment methods
30
+ - [What's New in v1.2](docs/WHATS_NEW_1.2.md) - New features and improvements
31
+ - [E2EE Setup Guide](docs/E2EE.md) - Matrix End-to-End Encryption configuration
32
32
 
33
33
  ---
34
34
 
35
35
  ## Plugins
36
36
 
37
- M<>M Relay supports plugins for extending its functionality, enabling customization and enhancement of the relay to suit specific needs.
37
+ MMRelay supports plugins for extending its functionality, enabling customization and enhancement of the relay to suit specific needs.
38
38
 
39
39
  ### Core Plugins
40
40
 
@@ -83,7 +83,7 @@ Plugins make it easy to extend functionality without modifying the core program.
83
83
 
84
84
  ## Getting Started with Matrix
85
85
 
86
- See our Wiki page [Getting Started With Matrix & MM Relay](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki/Getting-Started-With-Matrix-&-MM-Relay).
86
+ See our Wiki page [Getting Started With Matrix & MMRelay](https://github.com/jeremiah-k/meshtastic-matrix-relay/wiki/Getting-Started-With-Matrix-&-MM-Relay).
87
87
 
88
88
  ---
89
89
 
@@ -2,21 +2,21 @@ meshtastic>=2.6.4
2
2
  Pillow==11.3.0
3
3
  matrix-nio==0.25.2
4
4
  matplotlib==3.10.1
5
- requests==2.32.4
6
- markdown==3.8.2
5
+ requests==2.32.5
6
+ markdown==3.9
7
7
  bleach==6.2.0
8
8
  haversine==2.9.0
9
9
  schedule==1.2.2
10
- platformdirs==4.3.8
10
+ platformdirs==4.4.0
11
11
  py-staticmaps>=0.4.0
12
12
  psutil>=5.8.0
13
13
  rich==14.1.0
14
- setuptools==80.9.0
14
+ setuptools>=80.9.0 # Required for console script entry points and Windows compatibility
15
15
 
16
16
  # Testing and coverage
17
- coverage==7.10.3
18
- pytest==8.4.1
19
- pytest-cov==6.2.1
20
- pytest-asyncio==1.1.0
17
+ coverage==7.10.7
18
+ pytest==8.4.2
19
+ pytest-cov==6.3.0
20
+ pytest-asyncio==1.2.0
21
21
  pytest-env==1.1.5
22
22
  pytest-timeout==2.4.0
@@ -48,16 +48,16 @@ setup(
48
48
  "Pillow==11.3.0",
49
49
  "matrix-nio==0.25.2",
50
50
  "matplotlib==3.10.1",
51
- "requests==2.32.4",
52
- "markdown==3.8.2",
51
+ "requests==2.32.5",
52
+ "markdown==3.9",
53
53
  "bleach==6.2.0",
54
54
  "haversine==2.9.0",
55
55
  "schedule==1.2.2",
56
- "platformdirs==4.3.8",
56
+ "platformdirs==4.4.0",
57
57
  "py-staticmaps>=0.4.0",
58
58
  "psutil>=5.8.0",
59
59
  "rich==14.1.0",
60
- "setuptools==80.9.0",
60
+ "setuptools>=80.9.0", # Required for console script entry points and Windows compatibility
61
61
  ],
62
62
  extras_require={
63
63
  "e2e": [
@@ -68,6 +68,6 @@ setup(
68
68
  packages=find_packages(where="src"),
69
69
  package_dir={"": "src"},
70
70
  include_package_data=True,
71
- package_data={"mmrelay.tools": ["sample_config.yaml"]},
71
+ package_data={"mmrelay.tools": ["sample_config.yaml", "mmrelay.service"]},
72
72
  entry_points={"console_scripts": ["mmrelay = mmrelay.cli:main"]},
73
73
  )
@@ -2,4 +2,4 @@
2
2
  Meshtastic Matrix Relay - Bridge between Meshtastic mesh networks and Matrix chat rooms.
3
3
  """
4
4
 
5
- __version__ = "1.2.0"
5
+ __version__ = "1.2.2"
@@ -0,0 +1,29 @@
1
+ """
2
+ Alternative entry point for MMRelay that doesn't rely on setuptools console scripts.
3
+
4
+ This can be used as a fallback on Windows systems where the setuptools-generated
5
+ console script fails due to missing pkg_resources.
6
+
7
+ Usage:
8
+ python -m mmrelay [args...]
9
+ """
10
+
11
+ import sys
12
+
13
+ if __name__ == "__main__":
14
+ try:
15
+ from mmrelay.cli import main
16
+
17
+ sys.exit(main())
18
+ except ImportError as e:
19
+ print(f"Error importing MMRelay CLI: {e}", file=sys.stderr)
20
+ print("Please ensure MMRelay is properly installed.", file=sys.stderr)
21
+ sys.exit(1)
22
+ except KeyboardInterrupt:
23
+ print("Interrupted.", file=sys.stderr)
24
+ sys.exit(130)
25
+ except SystemExit:
26
+ raise
27
+ except Exception as e:
28
+ print(f"Unexpected error: {e}", file=sys.stderr)
29
+ sys.exit(1)