-
Notifications
You must be signed in to change notification settings - Fork 43
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
python: support status publishing on server #227
Conversation
cb458d2
to
bd6b7a0
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.
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")) |
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.
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.
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.
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) { |
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.
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.
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.
Sorry, this is a wonky diff because I changed the conditionals to early returns; was added in #224.
return; | ||
}; | ||
server.remove_status(status_ids); | ||
} |
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 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.
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.
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.
python/foxglove-sdk/src/lib.rs
Outdated
m.add_class::<PyCapability>()?; | ||
m.add_class::<PyClient>()?; | ||
m.add_class::<PyClientChannelView>()?; | ||
m.add_class::<PyStatus>()?; | ||
m.add_class::<PyStatusLevel>()?; |
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.
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?
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.
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.
let Some(server) = &self.0 else { | ||
return; | ||
}; | ||
server.clear_session(session_id); |
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.
Ultra-nit: you could write this a bit more succinctly:
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); | ||
} |
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.
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")) |
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.
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):
This adds
publish_status
andremove_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).