Conversation
This adds a write_layout() method to the MCAPWriter class that allows writing a Layout object to the MCAP file's metadata. The layout is serialized to JSON using the Layout.to_json() method and stored under the 'foxglove.layout' metadata key with an empty string key. Changes: - Created a Python wrapper class for MCAPWriter in mcap.py that adds the write_layout() method while delegating all other methods to the underlying Rust implementation - Updated foxglove.__init__.py to wrap the open_mcap function so it returns the Python MCAPWriter wrapper - Added a test for the write_layout functionality Co-authored-by: sebastian <sebastian@foxglove.dev>
|
Cursor Agent can help with this pull request. Just |
Use fully qualified name foxglove.open_mcap in the docstring to allow Sphinx to properly resolve the reference. Co-authored-by: sebastian <sebastian@foxglove.dev>
Co-authored-by: sebastian <sebastian@foxglove.dev>
Co-authored-by: sebastian <sebastian@foxglove.dev>
Instead of creating a Python wrapper class for MCAPWriter, add the write_layout method directly to the Rust PyMcapWriter implementation. This is cleaner and more consistent with the existing codebase. The method calls to_json() on the Layout object using PyO3 and stores the result in metadata under the 'foxglove.layout' key. Co-authored-by: sebastian <sebastian@foxglove.dev>
python/foxglove-sdk/src/mcap.rs
Outdated
| // Store in metadata with name "foxglove.layout" and empty key | ||
| let mut metadata = std::collections::BTreeMap::new(); | ||
| metadata.insert(String::new(), json_str); |
There was a problem hiding this comment.
@cursor let's add a layout_name parameter to the write_layout function. Use layout_name as the key here instead of an empty string.
There was a problem hiding this comment.
Done! I've added the layout_name parameter to the write_layout function.
Changes
Rust (python/foxglove-sdk/src/mcap.rs)
fn write_layout(&self, py: Python<'_>, layout: Py<PyAny>, layout_name: String) -> PyResult<()> {
let json_str: String = layout.call_method0(py, "to_json")?.extract(py)?;
let mut metadata = std::collections::BTreeMap::new();
metadata.insert(layout_name, json_str); // Uses layout_name as the key
// ...
}Type stub (mcap.pyi)
def write_layout(self, layout: "Layout", layout_name: str) -> None:
"""
:param layout: A Layout object from foxglove.layouts.
:param layout_name: The name to use as the key in the metadata record.
"""Test updated
layout_name = "my_test_layout"
writer.write_layout(layout, layout_name)
# Verifies that layout_name is used as the key in the metadata
assert layout_name in record.metadataThe layout_name parameter is used as the key in the metadata record instead of an empty string. Co-authored-by: sebastian <sebastian@foxglove.dev>
Changed write_layout to store layouts in an internal BTreeMap within PyMcapWriter instead of writing immediately. All accumulated layouts are written as a single metadata record with the name 'foxglove.layout' when the writer is closed. This allows multiple layouts to be stored in the same file with different names. - Added layouts field to PyMcapWriter struct - Updated close() to write accumulated layouts before closing - Updated test to verify multiple layouts are preserved Co-authored-by: sebastian <sebastian@foxglove.dev>
- Changed layout parameter type from Layout object to string - Reordered parameters: layout_name first, layout second - Changed metadata name from 'foxglove.layout' to 'foxglove.layouts' - Updated test to pass layout.to_json() as string - Removed unused Layout type import from mcap.pyi Co-authored-by: sebastian <sebastian@foxglove.dev>
Co-authored-by: sebastian <sebastian@foxglove.dev>
Adds a write_layout method that stores a layout JSON string as MCAP metadata under the 'foxglove.layouts' key with layout_name as the key within the metadata record. Co-authored-by: sebastian <sebastian@foxglove.dev>
rust/foxglove/src/mcap_writer.rs
Outdated
| /// ``` | ||
| pub fn write_layout(&self, layout_name: &str, layout: &str) -> Result<(), FoxgloveError> { | ||
| let mut metadata = std::collections::BTreeMap::new(); | ||
| metadata.insert(layout_name.to_string(), layout.to_string()); |
There was a problem hiding this comment.
@cursor this creates a new metadata object each time we call write_layout, so only the last layout will be saved. Can you ensure no layouts are lost if there are multiple calls to write_layout?
There was a problem hiding this comment.
Done! I've updated McapWriterHandle to accumulate layouts and write them all when closing.
Changes
rust/foxglove/src/mcap_writer.rs:
Added a layouts field with interior mutability to accumulate layouts:
pub struct McapWriterHandle<W: Write + Seek + Send + 'static> {
sink: Arc<McapSink<W>>,
context: Weak<Context>,
layouts: Mutex<BTreeMap<String, String>>, // New field
}Updated write_layout to add to the internal map instead of writing immediately:
pub fn write_layout(&self, layout_name: &str, layout: &str) {
self.layouts
.lock()
.unwrap()
.insert(layout_name.to_string(), layout.to_string());
}Updated finish() to write all accumulated layouts before closing:
fn finish(&self) -> Result<Option<W>, FoxgloveError> {
if let Some(context) = self.context.upgrade() {
context.remove_sink(self.sink.id());
}
// Write all accumulated layouts as a single metadata record
let layouts = std::mem::take(&mut *self.layouts.lock().unwrap());
if !layouts.is_empty() {
self.sink.write_metadata("foxglove.layouts", layouts)?;
}
self.sink.finish()
}Now multiple calls to write_layout will accumulate all layouts and write them together as a single metadata record when the writer is closed.
Added a layouts field (Mutex<BTreeMap>) to McapWriterHandle to store layouts internally. The write_layout method now adds to the internal map instead of writing immediately. All accumulated layouts are written as a single metadata record when the writer is closed, ensuring no layouts are lost when write_layout is called multiple times. Co-authored-by: sebastian <sebastian@foxglove.dev>


Changelog
Added
write_layoutmethod to the Python MCAP writer for storing Foxglove layouts in file metadata.Docs
Updated
MCAPWriterandopen_mcapdocumentation to reflect the newwrite_layoutmethod and the Python wrapper class.Description
The Python SDK's MCAP writer previously lacked a direct method to embed Foxglove
Layoutobjects into the MCAP file's metadata. This PR introduces awrite_layoutmethod to theMCAPWriterclass, allowing users to easily serialize afoxglove.layouts.Layoutobject to JSON and store it under the "foxglove.layout" metadata key.To achieve this, the underlying Rust-backed
_MCAPWriteris now wrapped by a new PythonMCAPWriterclass. Thefoxglove.open_mcapfunction has been updated to return this Python wrapper, ensuring that all existingMCAPWriterfunctionality remains available while adding the newwrite_layoutcapability. This change provides a more consistent and convenient API for embedding visualization layouts directly into MCAP files, improving their self-describing nature for Foxglove Studio.Verified by running existing MCAP tests and a new dedicated test case for
write_layoutthat confirms correct serialization and metadata storage.