Skip to content

Commit 2b6a4e8

Browse files
authored
fix: newer AppDaemon versions do not require the explicit mqtt_subscribe (#200)
1 parent 5aa522f commit 2b6a4e8

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

apps/qolsysgw/mqtt/listener.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ def __init__(self, app: Mqtt, namespace: str, topic: str,
1919
self._callback = callback or defaultLoggerCallback
2020
self._logger = logger or LOGGER
2121

22-
app.mqtt_subscribe(topic, namespace=namespace)
22+
# Note: mqtt_subscribe is intentionally NOT called here.
23+
# listen_event with event='MQTT_MESSAGE' handles both subscription
24+
# and callback registration in AppDaemon. Calling both mqtt_subscribe
25+
# and listen_event can cause duplicate event delivery in some
26+
# AppDaemon versions.
2327
app.listen_event(self.event_callback, event='MQTT_MESSAGE',
2428
topic=topic, namespace=namespace)
2529

tests/end-to-end/test_qolsysgw.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import re
66
import shlex
77
import subprocess
8+
import sys
89
import tempfile
910
import unittest
1011

@@ -79,6 +80,41 @@ def _docker_compose_down(self):
7980
self._docker_is_up = False
8081
return run
8182

83+
def _docker_fix_permissions_for_cleanup(self, service, path):
84+
"""Fix permissions on container-created files to allow temp directory cleanup.
85+
86+
Docker containers may create files with different ownership that the
87+
test process cannot delete. This chmod's them before stopping containers.
88+
"""
89+
try:
90+
self._docker_compose('exec', '-T', service, 'chmod', '-R', '777', path)
91+
except Exception:
92+
pass # Best effort - container might not be running
93+
94+
def _print_container_versions(self):
95+
"""Print the versions of the containers being used for debugging.
96+
97+
Uses sys.stderr to ensure output is visible even when pytest
98+
captures stdout.
99+
"""
100+
print('\n=== Container Versions ===', file=sys.stderr)
101+
for service, container_name in self.CONTAINERS.items():
102+
try:
103+
# Get the image name and digest
104+
result = subprocess.run(
105+
['docker', 'inspect', '--format',
106+
'{{.Config.Image}} ({{.Image}})', container_name],
107+
capture_output=True,
108+
text=True,
109+
)
110+
if result.returncode == 0:
111+
print(f'{service}: {result.stdout.strip()}', file=sys.stderr)
112+
else:
113+
print(f'{service}: unable to get version', file=sys.stderr)
114+
except Exception as e:
115+
print(f'{service}: error getting version - {e}', file=sys.stderr)
116+
print('=== End Container Versions ===\n', file=sys.stderr)
117+
82118
def setUp(self):
83119
self.CONTAINERS = {}
84120
self._tmpdir = tempfile.TemporaryDirectory(
@@ -88,6 +124,11 @@ def setUp(self):
88124

89125
def tearDown(self):
90126
if hasattr(self, '_docker_is_up') and self._docker_is_up:
127+
# Fix permissions on files created by containers before stopping them
128+
# This allows the temp directory cleanup to work properly
129+
self._docker_fix_permissions_for_cleanup('appdaemon', '/conf')
130+
self._docker_fix_permissions_for_cleanup('homeassistant', '/config')
131+
91132
# Stop and destroy containers
92133
self._docker_compose_down()
93134

@@ -131,6 +172,9 @@ async def get_context(self):
131172
# Start containers
132173
self._docker_compose_up()
133174

175+
# Print container versions for debugging
176+
self._print_container_versions()
177+
134178
# Grab logs from AppDaemon
135179
appdaemon = AppDaemonDockerLogReader(
136180
container_name=self.CONTAINERS['appdaemon'],

0 commit comments

Comments
 (0)