Skip to content

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

Merged
merged 12 commits into from
Feb 25, 2025

Conversation

bryfox
Copy link
Contributor

@bryfox bryfox commented Feb 21, 2025

This adds on_get_parameters and on_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.

Copy link

linear bot commented Feb 21, 2025

@bryfox bryfox requested review from gasmith and eloff February 21, 2025 17:11
Base automatically changed from bryan/fg-10180-python-register-a-server-listener-with-client_message to main February 21, 2025 17:52
@bryfox bryfox force-pushed the bryan/fg-10186-python-allow-user-to-set-parameters branch from 887f0c3 to 46c6ddb Compare February 21, 2025 17:56
Copy link
Contributor

@eloff eloff left a 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
Copy link
Contributor

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

Copy link
Contributor Author

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]
Copy link
Contributor

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.

Copy link
Contributor Author

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(
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@bryfox bryfox requested a review from eloff February 24, 2025 19:02
@bryfox
Copy link
Contributor Author

bryfox commented Feb 24, 2025

We can rename the callback to make it clearer, and maybe add some docs to clarify how it should be used.

I updated the docs here; I filed FG-10592 for possibly renaming.

Copy link
Contributor

@eloff eloff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bryfox bryfox merged commit 3d19421 into main Feb 25, 2025
29 checks passed
@bryfox bryfox deleted the bryan/fg-10186-python-allow-user-to-set-parameters branch February 25, 2025 14:44
bryfox added a commit that referenced this pull request Feb 25, 2025
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants