-
Notifications
You must be signed in to change notification settings - Fork 34
fix KeyError when stream_status is called on a group #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
fix KeyError when stream_status is called on a group #83
Conversation
|
Adding this check makes sense to me, but we should also fix the root cause. We know that adding/removing streams do not trigger an update notification (which should be fixed on the server side), see #65 python-snapcast/snapcast/control/server.py Line 449 in 566c977
Same needs to be done if we receive an _on _group_stream_changed notification with an unknown stream. And I think in both cases it would be good to call the on update callback. |
|
I am not 100% sure how the async is implemented in this lib. diff --git a/snapcast/control/server.py b/snapcast/control/server.py
index 6a0e570..62b2fd9 100644
--- a/snapcast/control/server.py
+++ b/snapcast/control/server.py
@@ -272,7 +271,12 @@ class Snapserver():
def stream(self, stream_identifier):
"""Get a stream."""
- return self._streams[stream_identifier]
+ try:
+ return self._streams[stream_identifier]
+ except KeyError:
+ _LOGGER.info('stream %s not found, synchronize', stream_identifier)
+ asyncio.ensure_future(self.sync_sync())
+ raise KeyError
def client(self, client_identifier):
"""Get a client."""
@@ -443,10 +447,10 @@ class Snapserver():
_LOGGER.debug('stream %s is input-only, ignore', data.get('id'))
else:
_LOGGER.info('stream %s not found, synchronize', data.get('id'))
+ asyncio.ensure_future(self.sync_sync())
- async def async_sync():
- self.synchronize((await self.status())[0])
- asyncio.ensure_future(async_sync())
+ async def async_sync(self):
+ self.synchronize((await self.status())[0])
def set_on_update_callback(self, func):
"""Set on update callback function.""
@@ -373,6 +377,10 @@ class Snapserver():
def _on_group_stream_changed(self, data):
"""Handle group stream change."""
group = self._groups.get(data.get('id'))
+ stream_id = data.get('stream_id')
+ if stream_id not in self._streams:
+ _LOGGER.info('stream %s not found, synchronize', stream_id)
+ asyncio.ensure_future(self.sync_sync())
group.update_stream(data)
for client_id in group.clients:
self._clients.get(client_id).callback() |
for stream and _on_group_stream_changed calls
luar123
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments
snapcast/control/server.py
Outdated
| def stream(self, stream_identifier): | ||
| """Get a stream.""" | ||
| if stream_identifier not in self._streams: | ||
| self._synchronize_if_stream_missing(stream_identifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we should add it to stream() as well or let the calling application handle it. Behavior is kind of strange as it raises a keyerror and then updates. @happyleavesaoc what do you think?
snapcast/control/server.py
Outdated
| def _on_group_stream_changed(self, data): | ||
| """Handle group stream change.""" | ||
| group = self._groups.get(data.get('id')) | ||
| self._synchronize_if_stream_missing(data.get('stream_id', None)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this unified function makes sense. Here, if stream is missing you need to call _on_update_callback_func, group.update_stream and the client callback after the sync, but in on_stream_update you only need to call _on_update_callback_func.
| """Handle group stream change.""" | ||
| group = self._groups.get(data.get('id')) | ||
| self._synchronize_if_stream_missing(data.get('stream_id', None)) | ||
| group.update_stream(data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proceed only if stream exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did updated the code and added a callback handler to _synchronize_if_stream_missing.
Co-authored-by: luar123 <49960470+luar123@users.noreply.github.com>
This pull request improves error handling in the
stream_statusproperty of theSnapgroupclass and adds a corresponding unit test to ensure robustness when a requested stream is missing from the server.Error handling improvements:
stream_statusproperty insnapcast/control/group.pyto catchKeyErrorexceptions and return"unknown"if the stream ID is not found, preventing unhandled exceptions."unknown"matches a valid state of the snapcast server API:https://github.com/snapcast/snapcast/blob/801c02eaa432e6715fd69a2b5d857d276c0e8c39/server/streamreader/properties.hpp#L62
Testing enhancements:
test_bad_stream_statusintests/test_group.pyto verify thatstream_statusreturns"unknown"when the stream ID does not exist on the server, ensuring the new error handling logic works as expected.Related to:
home-assistant/core#157636