forked from rerun-io/rerun
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Plumb through initial grpc support for the python SDK (rerun-io#7994)
### What - Adds a new `rr.remote` module - Gated by a new `remote` feature on `rerun_py` - Simple plumbing just for the `list_recordings` API: ``` pixi run py-build --features remote ``` ```python import rerun as rr conn = rr.remote.connect("http://0.0.0.0:51234") print("Recordings:") for rec in conn.list_recordings(): print(f" - {rec}") ``` ``` Recordings: - Recording(id=58474dc9-4120-4d15-aa83-95f6a9e5a203) ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7994?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7994?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7994) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`.
- Loading branch information
Showing
7 changed files
with
120 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from __future__ import annotations | ||
|
||
try: | ||
from rerun_bindings import ( | ||
connect as connect, | ||
) | ||
except ImportError: | ||
|
||
def connect(url: str) -> None: | ||
raise NotImplementedError("Rerun SDK was built without the `remote` feature enabled.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,6 @@ mod arrow; | |
mod dataframe; | ||
mod python_bridge; | ||
mod video; | ||
|
||
#[cfg(feature = "remote")] | ||
mod remote; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#![allow(unsafe_op_in_unsafe_fn)] | ||
// False positive due to #[pyfunction] macro | ||
use pyo3::{exceptions::PyRuntimeError, prelude::*, Bound, PyResult}; | ||
use re_remote_store_types::v0::{storage_node_client::StorageNodeClient, ListRecordingsRequest}; | ||
|
||
/// Register the `rerun.remote` module. | ||
pub(crate) fn register(m: &Bound<'_, PyModule>) -> PyResult<()> { | ||
m.add_function(wrap_pyfunction!(connect, m)?)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn connect_async(addr: String) -> PyResult<StorageNodeClient<tonic::transport::Channel>> { | ||
#[cfg(not(target_arch = "wasm32"))] | ||
let tonic_client = tonic::transport::Endpoint::new(addr) | ||
.map_err(|err| PyRuntimeError::new_err(err.to_string()))? | ||
.connect() | ||
.await | ||
.map_err(|err| PyRuntimeError::new_err(err.to_string()))?; | ||
|
||
Ok(StorageNodeClient::new(tonic_client)) | ||
} | ||
|
||
#[pyfunction] | ||
pub fn connect(addr: String) -> PyResult<PyConnection> { | ||
let runtime = tokio::runtime::Builder::new_current_thread() | ||
.enable_all() | ||
.build()?; | ||
|
||
let client = runtime.block_on(connect_async(addr))?; | ||
|
||
Ok(PyConnection { runtime, client }) | ||
} | ||
|
||
/// A connection to a remote storage node. | ||
#[pyclass(name = "Connection")] | ||
pub struct PyConnection { | ||
/// A tokio runtime for async operations. This connection will currently | ||
/// block the Python interpreter while waiting for responses. | ||
/// This runtime must be persisted for the lifetime of the connection. | ||
runtime: tokio::runtime::Runtime, | ||
|
||
/// The actual tonic connection. | ||
client: StorageNodeClient<tonic::transport::Channel>, | ||
} | ||
|
||
#[pymethods] | ||
impl PyConnection { | ||
/// List all recordings registered with the node. | ||
fn list_recordings(&mut self) -> PyResult<Vec<PyRecordingInfo>> { | ||
self.runtime.block_on(async { | ||
let request = ListRecordingsRequest {}; | ||
|
||
let resp = self | ||
.client | ||
.list_recordings(request) | ||
.await | ||
.map_err(|err| PyRuntimeError::new_err(err.to_string()))?; | ||
|
||
Ok(resp | ||
.into_inner() | ||
.recordings | ||
.into_iter() | ||
.map(|recording| PyRecordingInfo { info: recording }) | ||
.collect()) | ||
}) | ||
} | ||
} | ||
|
||
/// The info for a recording stored in the archive. | ||
#[pyclass(name = "RecordingInfo")] | ||
pub struct PyRecordingInfo { | ||
info: re_remote_store_types::v0::RecordingInfo, | ||
} | ||
|
||
#[pymethods] | ||
impl PyRecordingInfo { | ||
fn __repr__(&self) -> String { | ||
format!( | ||
"Recording(id={})", | ||
self.info.id.as_ref().map_or("Unknown", |id| id.id.as_str()) | ||
) | ||
} | ||
} |