Skip to content

python: support status publishing on server #227

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 4 commits into from
Feb 24, 2025

Conversation

bryfox
Copy link
Contributor

@bryfox bryfox commented Feb 20, 2025

This adds publish_status and remove_status to the Python server interface, to match the Rust SDK.

I've also updated the existing server methods to not raise exceptions, since the Rust SDK doesn't return resuts. Currently, the only way for these to fail is if the server has been shut down.

This is based on #226 to minimize conflicts (because that re-organized the structure of the server-related code).

Copy link

linear bot commented Feb 20, 2025

@bryfox bryfox requested review from eloff and gasmith February 20, 2025 16:19
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-10188-python-support-send_status-remove_status branch from cb458d2 to bd6b7a0 Compare February 21, 2025 17:54
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.

I think I'd be better to drop the status class and use regular arguments. I'm going to approve this same leave it up to you.

Exercise the server interface; will also be checked with mypy.
"""
server = start_server()
server.publish_status(Status(StatusLevel.Info, "test", "some-id"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we can just make these function arguments, instead of using a class like rust does. Saves an allocation, which doesn't matter much here. But it also is one less type for the user to care about.

Copy link
Contributor

Choose a reason for hiding this comment

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

Strongly agree. I had similar feedback on the rust PR about making this a bit more ergonomic. Maybe:

def publish_status(level: StatusLevel, message: str, id: str | None = None):

}

/// Publishes the current server timestamp to all clients.
pub fn broadcast_time(&self, timestamp_nanos: u64) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this from another PR that you used as a base? Not a big deal, I'll review that one next. You can figure out the logistics around merging them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, this is a wonky diff because I changed the conditionals to early returns; was added in #224.

return;
};
server.remove_status(status_ids);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

A bigger question about the API. Is it better to silently fail after the server is closed, or to throw an exception?

Since the default is to only close the server at exit, this seems ok to me as-is.

Copy link
Contributor

Choose a reason for hiding this comment

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

Either way, we should probably document that behavior.

It would be user-friendlier to not raise an exception, so that users aren't forced to litter their code with with contextlib.suppress(...): statements, but my rusty side says it's better to explicitly raise errors instead of trying to guess what the user was trying to do. Since we're trying to gear our python SDK towards user-friendliness, I suppose I agree with Dan.

Comment on lines 213 to 217
m.add_class::<PyCapability>()?;
m.add_class::<PyClient>()?;
m.add_class::<PyClientChannelView>()?;
m.add_class::<PyStatus>()?;
m.add_class::<PyStatusLevel>()?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Since these have fairly generic names ("capability", "client", "status", etc.), we chose to nest them under the websocket module in rust. Should we do the same in python?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I'd certainly like to re-organize this. Since there are a few concurrent PRs in-flight, I'd like to take a pass at that in a follow-up PR. I think it's mildly unfortunate we're baking the name "websocket" into these interfaces, but I'll likely follow whatever rust does in the end.

Comment on lines 144 to 147
let Some(server) = &self.0 else {
return;
};
server.clear_session(session_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ultra-nit: you could write this a bit more succinctly:

Suggested change
let Some(server) = &self.0 else {
return;
};
server.clear_session(session_id);
if let Some(server) = &self.0 {
server.clear_session(session_id);
}

return;
};
server.remove_status(status_ids);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Either way, we should probably document that behavior.

It would be user-friendlier to not raise an exception, so that users aren't forced to litter their code with with contextlib.suppress(...): statements, but my rusty side says it's better to explicitly raise errors instead of trying to guess what the user was trying to do. Since we're trying to gear our python SDK towards user-friendliness, I suppose I agree with Dan.

Exercise the server interface; will also be checked with mypy.
"""
server = start_server()
server.publish_status(Status(StatusLevel.Info, "test", "some-id"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Strongly agree. I had similar feedback on the rust PR about making this a bit more ergonomic. Maybe:

def publish_status(level: StatusLevel, message: str, id: str | None = None):

@bryfox bryfox merged commit acd8df9 into main Feb 24, 2025
28 checks passed
@bryfox bryfox deleted the bryan/fg-10188-python-support-send_status-remove_status branch February 24, 2025 16:56
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.

3 participants