-
Notifications
You must be signed in to change notification settings - Fork 43
python: implement parameters on server listener #231
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
python: implement parameters on server listener #231
Conversation
887f0c3
to
46c6ddb
Compare
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.
It was surprising behavior to me too.
We can rename the callback to make it clearer, and maybe add some docs to clarify how it should be used.
request_id: Optional[str] = None, | ||
) -> list[Parameter]: | ||
logging.debug(f"on_get_parameters: {param_names}, {client.id}, {request_id}") | ||
return self.parameters |
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.
This is ignoring the param names, that seems like the wrong thing to do in an example
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.
oh yes, good catch
request_id: str | None = None, | ||
) -> list[foxglove.Parameter]: | ||
logging.debug(f"on_set_parameters: {parameters}, {client.id}, {request_id}") | ||
existing_names = [p.name for p in self.parameters] |
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.
I think self.parameters should be a dict. See the rust example.
If you wanted to keep this as is you could use a set or dict comprehension.
Using list everywhere is simple but inefficient. I know it's only an example, but I like setting a good example.
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.
I originally wrote it with a dict, but thought that it got in the way of understanding the interface. I suppose having a lot of parameters could be typical; I'll update.
initial_values: list[Parameter] = [ | ||
Parameter( | ||
"param1", | ||
value=ParameterValue.Dict( |
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.
I see what you mean. This would be a much nicer interface in Python if you could just use native lists, dicts, bytes, etc and we did the conversion in our code.
Although we'd have to throw an exception at runtime if you passed the wrong type.
I feel like we could provide the correct typings though. Also this current code will still throw an exception at runtime if you pass the wrong types. So it's only slightly safer.
I guess for now this works and we can make it more ergonomic in a future iteration.
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.
I think it's reasonable to support both, so I'll keep this and have also filed FG-10589 for the alternative.
I updated the docs here; I filed FG-10592 for possibly renaming. |
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.
LGTM
This builds on #231 to add parameter subscription support to the Python SDK. The SDK takes care of all bookkeeping and this is purely informational for an implementer. This also removes "parametersSubscribe" from the public SDK. Because the SDK manages the subscriptions itself, as long as the client advertises the "parameters" capability, the SDK will automatically include the former capability. This does mean that the server listener callbacks would be called regardless, but both languages provide default no-op implementations.
This adds
on_get_parameters
andon_set_parameters
to the python server listener, along with an example.I was a bit surprised by the behavior of the latter, and only understood it by reading the ws-protocol spec; it works more like a patch interface. I updated the docs slightly to clarify this, but I wonder if we should consider renaming the callback for this. (Would we also consider implementing a parameter store internally in a future version?)
I think we'll eventually want a higher-level interface in Python for this too — dealing with 'type' classes is not ergonomic — but having a consistent interface seems valuable as well.