diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index 59f5be324598..f4a1a30d2f4f 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -19,7 +19,6 @@ use crate::{ objects::ObjectClass, ArrowRegistry, CodeGenerator, Docs, ElementType, GeneratedFiles, Object, ObjectField, ObjectKind, Objects, Reporter, Type, ATTR_PYTHON_ALIASES, ATTR_PYTHON_ARRAY_ALIASES, - ATTR_RERUN_LOG_MISSING_AS_EMPTY, }; use self::views::code_for_view; @@ -592,11 +591,7 @@ fn code_for_struct( } else if *kind == ObjectKind::Archetype { // Archetypes use the ComponentBatch constructor for their fields let (typ_unwrapped, _) = quote_field_type_from_field(objects, field, true); - if field.is_nullable && !obj.attrs.has(ATTR_RERUN_LOG_MISSING_AS_EMPTY) { - format!("converter={typ_unwrapped}Batch._optional, # type: ignore[misc]\n") - } else { - format!("converter={typ_unwrapped}Batch._required, # type: ignore[misc]\n") - } + format!("converter={typ_unwrapped}Batch._converter, # type: ignore[misc]\n") } else if !default_converter.is_empty() { code.push_indented(0, &converter_function, 1); format!("converter={default_converter}") @@ -699,6 +694,7 @@ fn code_for_struct( if obj.kind == ObjectKind::Archetype { code.push_indented(1, quote_clear_methods(obj), 2); + code.push_indented(1, quote_partial_update_methods(reporter, obj, objects), 2); } if obj.is_delegating_component() { @@ -739,10 +735,7 @@ fn code_for_struct( }; let metadata = if *kind == ObjectKind::Archetype { - format!( - "\nmetadata={{'component': '{}'}}, ", - if *is_nullable { "optional" } else { "required" } - ) + "\nmetadata={'component': True}, ".to_owned() } else { String::new() }; @@ -756,7 +749,7 @@ fn code_for_struct( String::new() }; // Note: mypy gets confused using staticmethods for field-converters - let typ = if !*is_nullable { + let typ = if !obj.is_archetype() && !*is_nullable { format!("{typ} = field(\n{metadata}{converter}{type_ignore}\n)") } else { format!( @@ -2336,60 +2329,57 @@ fn quote_init_parameter_from_field( } } -fn quote_init_method( - reporter: &Reporter, - obj: &Object, - ext_class: &ExtensionClass, - objects: &Objects, -) -> String { +fn compute_init_parameters(obj: &Object, objects: &Objects) -> Vec { // If the type is fully transparent (single non-nullable field and not an archetype), // we have to use the "{obj.name}Like" type directly since the type of the field itself might be too narrow. // -> Whatever type aliases there are for this type, we need to pick them up. - let parameters: Vec<_> = - if obj.kind != ObjectKind::Archetype && obj.fields.len() == 1 && !obj.fields[0].is_nullable - { - vec![format!( - "{}: {}", - obj.fields[0].name, - quote_parameter_type_alias(&obj.fqname, &obj.fqname, objects, false) - )] - } else if obj.is_union() { - vec![format!( - "inner: {} | None = None", - quote_parameter_type_alias(&obj.fqname, &obj.fqname, objects, false) - )] - } else { - let required = obj - .fields - .iter() - .filter(|field| !field.is_nullable) - .map(|field| quote_init_parameter_from_field(field, objects, &obj.fqname)) - .collect_vec(); - - let optional = obj - .fields - .iter() - .filter(|field| field.is_nullable) - .map(|field| quote_init_parameter_from_field(field, objects, &obj.fqname)) - .collect_vec(); - - if optional.is_empty() { - required - } else if obj.kind == ObjectKind::Archetype { - // Force kw-args for all optional arguments: - required - .into_iter() - .chain(std::iter::once("*".to_owned())) - .chain(optional) - .collect() - } else { - required.into_iter().chain(optional).collect() - } - }; + if obj.kind != ObjectKind::Archetype && obj.fields.len() == 1 && !obj.fields[0].is_nullable { + vec![format!( + "{}: {}", + obj.fields[0].name, + quote_parameter_type_alias(&obj.fqname, &obj.fqname, objects, false) + )] + } else if obj.is_union() { + vec![format!( + "inner: {} | None = None", + quote_parameter_type_alias(&obj.fqname, &obj.fqname, objects, false) + )] + } else { + let required = obj + .fields + .iter() + .filter(|field| !field.is_nullable) + .map(|field| quote_init_parameter_from_field(field, objects, &obj.fqname)) + .collect_vec(); - let head = format!("def __init__(self: Any, {}):", parameters.join(", ")); + let optional = obj + .fields + .iter() + .filter(|field| field.is_nullable) + .map(|field| quote_init_parameter_from_field(field, objects, &obj.fqname)) + .collect_vec(); + + if optional.is_empty() { + required + } else if obj.kind == ObjectKind::Archetype { + // Force kw-args for all optional arguments: + required + .into_iter() + .chain(std::iter::once("*".to_owned())) + .chain(optional) + .collect() + } else { + required.into_iter().chain(optional).collect() + } + } +} - let parameter_docs = if obj.is_union() { +fn compute_init_parameter_docs( + reporter: &Reporter, + obj: &Object, + objects: &Objects, +) -> Vec { + if obj.is_union() { Vec::new() } else { obj.fields @@ -2414,7 +2404,19 @@ fn quote_init_method( } }) .collect::>() - }; + } +} + +fn quote_init_method( + reporter: &Reporter, + obj: &Object, + ext_class: &ExtensionClass, + objects: &Objects, +) -> String { + let parameters = compute_init_parameters(obj, objects); + let head = format!("def __init__(self: Any, {}):", parameters.join(", ")); + + let parameter_docs = compute_init_parameter_docs(reporter, obj, objects); let mut doc_string_lines = vec![format!( "Create a new instance of the {} {}.", obj.name, @@ -2474,7 +2476,7 @@ fn quote_clear_methods(obj: &Object) -> String { let param_nones = obj .fields .iter() - .map(|field| format!("{} = None, # type: ignore[arg-type]", field.name)) + .map(|field| format!("{} = None,", field.name)) .join("\n "); let classname = &obj.name; @@ -2497,6 +2499,98 @@ fn quote_clear_methods(obj: &Object) -> String { )) } +fn quote_partial_update_methods(reporter: &Reporter, obj: &Object, objects: &Objects) -> String { + let name = &obj.name; + + let parameters = obj + .fields + .iter() + .map(|field| { + let mut field = field.clone(); + field.is_nullable = true; + quote_init_parameter_from_field(&field, objects, &obj.fqname) + }) + .collect_vec() + .join(", "); + + let kwargs = obj + .fields + .iter() + .map(|field| { + let field_name = field.snake_case_name(); + format!("'{field_name}': {field_name}") + }) + .collect_vec() + .join(", "); + + let parameter_docs = compute_init_parameter_docs(reporter, obj, objects); + let mut doc_string_lines = vec![format!("Update only some specific fields of a `{name}`.")]; + if !parameter_docs.is_empty() { + doc_string_lines.push("\n".to_owned()); + doc_string_lines.push("Parameters".to_owned()); + doc_string_lines.push("----------".to_owned()); + doc_string_lines.push("clear:".to_owned()); + doc_string_lines + .push(" If true, all unspecified fields will be explicitly cleared.".to_owned()); + for doc in parameter_docs { + doc_string_lines.push(doc); + } + }; + let doc_block = quote_doc_lines(doc_string_lines) + .lines() + .map(|line| format!(" {line}")) + .collect_vec() + .join("\n"); + + let field_clears = obj + .fields + .iter() + .map(|field| { + let field_name = field.snake_case_name(); + format!("{field_name}=[],") + }) + .collect_vec() + .join("\n "); + let field_clears = indent::indent_by(4, field_clears); + + unindent(&format!( + r#" + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + {parameters}, + ) -> {name}: + +{doc_block} + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = {{ + {kwargs}, + }} + + if clear: + kwargs = {{k: v if v is not None else [] for k, v in kwargs.items()}} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> {name}: + """Clear all the fields of a `{name}`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + {field_clears} + ) + return inst + "# + )) +} + // --- Arrow registry code generators --- use arrow2::datatypes::{DataType, Field, UnionMode}; diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index f77453ae1a2e..abd75b46af08 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -72,6 +72,7 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Capsules3D`](https://rerun.io/docs/reference/types/archetypes/capsules3d)** | `archetypes/capsules3d_batch` | Log a batch of capsules | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/capsules3d_batch.cpp) | | **[`Clear`](https://rerun.io/docs/reference/types/archetypes/clear)** | `archetypes/clear_simple` | Log and then clear data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.cpp) | | **[`Clear`](https://rerun.io/docs/reference/types/archetypes/clear)** | `archetypes/clear_recursive` | Log and then clear data recursively | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.cpp) | +| **[`Clear`](https://rerun.io/docs/reference/types/archetypes/clear)** | `archetypes/transform3d_partial_updates` | Log different transforms with visualized coordinates axes | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp) | | **[`Clear`](https://rerun.io/docs/reference/types/archetypes/clear)** | `concepts/different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **[`DepthImage`](https://rerun.io/docs/reference/types/archetypes/depth_image)** | `archetypes/depth_image_simple` | Create and log a depth image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_simple.cpp) | | **[`DepthImage`](https://rerun.io/docs/reference/types/archetypes/depth_image)** | `archetypes/depth_image_3d` | Create and log a depth image and pinhole camera | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_3d.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_3d.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/depth_image_3d.cpp) | @@ -200,9 +201,7 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes/annotation_context_connections` | Log annotation context with connections between keypoints | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/annotation_context_connections.cpp) | | **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `archetypes/segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | | **[`AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context)** | `tutorials/annotation-context` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/annotation-context.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/annotation-context.rs) | | -| **[`ClassId`](https://rerun.io/docs/reference/types/components/class_id)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`ClassId`](https://rerun.io/docs/reference/types/components/class_id)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `archetypes/points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts/different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | @@ -221,13 +220,11 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **[`ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer)** | `archetypes/image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | | **[`ImageFormat`](https://rerun.io/docs/reference/types/components/image_format)** | `archetypes/image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | -| **[`KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `archetypes/text_document` | Log a `TextDocument` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.cpp) | | **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `views/text_document` | Use a blueprint to show a text document | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_document.py) | | | | **[`Plane3D`](https://rerun.io/docs/reference/types/components/plane3d)** | `views/spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/mesh3d_partial_updates` | Log a simple colored triangle, then update its vertices' positions each frame | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_builtin_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.cpp) | @@ -239,7 +236,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/line_strips2d_ui_radius` | Log lines with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_ui_radius.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/geo_points_simple` | Log some very simple geospatial point | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.cpp) | -| **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `concepts/different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `views/map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | @@ -261,7 +257,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views/dataframe` | Use a blueprint to customize a DataframeView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/dataframe.py) | | | | **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views/tensor` | Use a blueprint to show a tensor view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/tensor.py) | | | | **[`Scalar`](https://rerun.io/docs/reference/types/components/scalar)** | `views/timeseries` | Use a blueprint to customize a TimeSeriesView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/timeseries.py) | | | -| **[`ShowLabels`](https://rerun.io/docs/reference/types/components/show_labels)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`ShowLabels`](https://rerun.io/docs/reference/types/components/show_labels)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`TensorDimensionIndexSelection`](https://rerun.io/docs/reference/types/components/tensor_dimension_index_selection)** | `views/tensor` | Use a blueprint to show a tensor view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/tensor.py) | | | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `views/text_log` | Use a blueprint to show a text log | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_log.py) | | | @@ -270,7 +265,6 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes/text_log` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_log.cpp) | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes/text_document` | Log a `TextDocument` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.cpp) | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes/entity_path` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/entity_path.cpp) | -| **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes/points3d_partial_updates` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp) | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `archetypes/points3d_partial_updates_legacy` | Demonstrates usage of the new partial updates APIs | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp) | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `concepts/app-model/native-async` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-async.cpp) | | **[`Text`](https://rerun.io/docs/reference/types/components/text)** | `concepts/app-model/native-sync` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/app-model/native-sync.cpp) | diff --git a/docs/snippets/all/archetypes/points3d_partial_updates.py b/docs/snippets/all/archetypes/points3d_partial_updates.py index 69f56d5c62ae..f97d4b766b06 100644 --- a/docs/snippets/all/archetypes/points3d_partial_updates.py +++ b/docs/snippets/all/archetypes/points3d_partial_updates.py @@ -14,23 +14,7 @@ radii = [0.6 if n < i else 0.2 for n in range(0, 10)] rr.set_time_sequence("frame", i) - rr.log("points", [rr.Points3D.indicator(), rr.components.ColorBatch(colors), rr.components.RadiusBatch(radii)]) - # TODO(cmc): implement new APIs and use them! - # rr.log("points", rr.Points3D.update_fields(radii=radii, colors=colors)) + rr.log("points", rr.Points3D.update_fields(radii=radii, colors=colors)) rr.set_time_sequence("frame", 20) -rr.log( - "points", - [ - rr.Points3D.indicator(), - rr.components.Position3DBatch(positions), - rr.components.RadiusBatch(0.3), - rr.components.ColorBatch([]), - rr.components.TextBatch([]), - rr.components.ShowLabelsBatch([]), - rr.components.ClassIdBatch([]), - rr.components.KeypointIdBatch([]), - ], -) -# TODO(cmc): implement new APIs and use them! -# rr.log("points", rr.Points3D.clear_fields().update_fields(positions=positions, radii=0.3)) +rr.log("points", rr.Points3D.update_fields(clear=True, positions=positions, radii=0.3)) diff --git a/docs/snippets/all/archetypes/transform3d_partial_updates.py b/docs/snippets/all/archetypes/transform3d_partial_updates.py index 1b05dd5db502..fba4a436cd49 100644 --- a/docs/snippets/all/archetypes/transform3d_partial_updates.py +++ b/docs/snippets/all/archetypes/transform3d_partial_updates.py @@ -11,43 +11,44 @@ def truncated_radians(deg: float) -> float: rr.init("rerun_example_transform3d_partial_updates", spawn=True) +# Set up a 3D box. rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), - rr.Transform3D(axis_length=10), + rr.Transform3D(clear=False, axis_length=10), ) +# Update only the rotation of the box. for deg in range(46): rad = truncated_radians(deg * 4) - # TODO(#8582): update_fields rr.log( "box", - rr.Transform3D( + rr.Transform3D.update_fields( # TODO(cmc): we should have access to all the fields of the extended constructor too. rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) +# Update only the position of the box. for t in range(51): - # TODO(#8582): update_fields rr.log( "box", - rr.Transform3D(translation=[0, 0, t / 10.0]), + rr.Transform3D.update_fields(translation=[0, 0, t / 10.0]), ) +# Update only the rotation of the box. for deg in range(46): rad = truncated_radians((deg + 45) * 4) - # TODO(#8582): update_fields rr.log( "box", - rr.Transform3D( + rr.Transform3D.update_fields( # TODO(cmc): we should have access to all the fields of the extended constructor too. rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) -# TODO(#8582): update_fields(clear=True) +# Clear all of the box's attributes, and reset its axis length. rr.log( "box", - rr.Transform3D(axis_length=15), + rr.Transform3D.update_fields(clear=True, axis_length=15), ) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 6b66945e367c..3001e5c1b9dc 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -273,7 +273,6 @@ quick_start = [ # These examples don't have exactly the same implementation. ] "archetypes/transform3d_partial_updates" = [ "cpp", # TODO(#8583): remove once C++ partial updates APIs have shipped - "py", # TODO(#8582): remove once Python partial updates APIs have shipped ] "archetypes/instance_poses3d_combined" = [ # TODO(#3235): Slight floating point differences in point grid. "cpp", diff --git a/pixi.lock b/pixi.lock index ad8fed5b1757..999d8638a8e1 100644 --- a/pixi.lock +++ b/pixi.lock @@ -125,7 +125,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.1-py311h2dc5d0c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nasm-2.16.03-h4bc722e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda @@ -353,7 +353,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -570,7 +570,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -786,7 +786,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.1-py311h0ecf0c1_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -973,7 +973,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -1194,7 +1194,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nasm-2.16.03-h4bc722e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda @@ -1406,7 +1406,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -1607,7 +1607,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -1806,7 +1806,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -1993,7 +1993,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -6121,7 +6121,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-common-9.0.1-h266115a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-libs-9.0.1-he0572af_1.conda @@ -6466,7 +6466,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -6765,7 +6765,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -7050,7 +7050,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -7322,7 +7322,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -7577,7 +7577,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.1-py311h2dc5d0c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nasm-2.16.03-h4bc722e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda @@ -7815,7 +7815,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -8042,7 +8042,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -8267,7 +8267,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-3.0.1-py311h0ecf0c1_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -8480,7 +8480,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -8814,7 +8814,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-common-9.0.1-h266115a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-libs-9.0.1-he0572af_1.conda @@ -9356,7 +9356,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -9841,7 +9841,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -10321,7 +10321,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -10771,7 +10771,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -11296,7 +11296,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.1.0-py311h2dc5d0c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-common-9.0.1-h266115a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mysql-libs-9.0.1-he0572af_1.conda @@ -11661,7 +11661,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-3.0.1-py311ha09ea12_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.1.0-py311h58d527c_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nasm-2.16.03-h68df207_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.5-hcccb83c_1.conda @@ -11980,7 +11980,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-3.0.1-py311ha971863_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.1.0-py311h1cc1194_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nasm-2.16.03-hfdf4475_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.5-hf036a51_1.conda @@ -12286,7 +12286,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.1.0-py311h30e7462_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nasm-2.16.03-h99b78c6_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda @@ -12562,7 +12562,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_694.conda - conda: https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/multidict-6.1.0-py311h5082efb_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nasm-2.16.03-hfd05255_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda @@ -26010,73 +26010,84 @@ packages: - numpy - rerun-sdk editable: true -- conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda - sha256: 943c43f2d68a6d4e8fa8a3a4e62538e090f5f0afe551f50092ea024850f5cccb - md5: 93b7b2391a045cea0d97772f550f1d77 +- conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.14.1-py311h9ecbd09_0.conda + sha256: 583282ca209e9dc9f91e28bb4d47bbf31456c2d437a4b4bdc3b1684b916b6264 + md5: 2bf2e229fee8e7649a7567dc61156437 depends: - - libgcc-ng >=12 + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 - mypy_extensions >=1.0.0 - psutil >=4.0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - typing_extensions >=4.1.0 + arch: x86_64 + platform: linux license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 17719191 - timestamp: 1703185056003 -- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda - sha256: 2a1d84dc94a02ed3cae2fad6dfea0fab4a9504649c1a009d1fff7bfbd9d48e57 - md5: 22b4d0e0a591e6dba331d95f8a702517 + size: 18730461 + timestamp: 1735601000085 +- conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.14.1-py311ha879c10_0.conda + sha256: dc6f8258ebb3539b6ab27b5a78a1d2339b99a19c6396d29ffa3286664b0d671d + md5: e9e333fbbbc7571fb70f8e47edafdddd depends: - - libgcc-ng >=12 + - libgcc >=13 - mypy_extensions >=1.0.0 - psutil >=4.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - typing_extensions >=4.1.0 + arch: aarch64 + platform: linux license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 15129179 - timestamp: 1703185374507 -- conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda - sha256: affdf64692efcf05888cc42fc2c4159fe5bade7d610847b5610e5b2cc621cd3a - md5: c32cbc41e84a67f1b30b3f157b46996b + size: 16065092 + timestamp: 1735600817630 +- conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.14.1-py311h4d7f069_0.conda + sha256: 5b5043cb2eeec8d0821130bf0e7ef62df44cbcff7220dca7e8497382f39f40b1 + md5: 285e86076c2a98bb57c7080a11095c69 depends: + - __osx >=10.13 - mypy_extensions >=1.0.0 - psutil >=4.0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - typing_extensions >=4.1.0 + arch: x86_64 + platform: osx license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 11969071 - timestamp: 1703184938293 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda - sha256: e31c811f99b842020350f9df6c6e4b5e2bf07353fee3cc0029c655e8980d9431 - md5: 93010b2e72e263002f6c60dc1c1f7e1d + size: 12710578 + timestamp: 1735600553201 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.14.1-py311h917b07b_0.conda + sha256: 0d891fd3d73ddcece659e62b765ddd6023b1296d69943481dc9910107071307a + md5: c09549d23170ecaabfa4a8162b5d4f10 depends: + - __osx >=11.0 - mypy_extensions >=1.0.0 - psutil >=4.0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - typing_extensions >=4.1.0 + arch: arm64 + platform: osx license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 9655583 - timestamp: 1703185105616 -- conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda - sha256: cebfab3f247a752be06e945a3a2a1281195d6917fa09906a9618dbc7b2cf734e - md5: 9a949cc91276bf313755857a11ce1ec3 + size: 10180870 + timestamp: 1735600589567 +- conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.14.1-py311he736701_0.conda + sha256: 12a90fb2507dd5c56a0e846bf828fe8b3197aa79ec8d655934d455d20101a640 + md5: a3f3aebd6fbdbdec85098e24d14f89aa depends: - mypy_extensions >=1.0.0 - psutil >=4.0 @@ -26086,12 +26097,14 @@ packages: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 + arch: x86_64 + platform: win license: MIT license_family: MIT purls: - pkg:pypi/mypy?source=hash-mapping - size: 9963457 - timestamp: 1703184979309 + size: 10553025 + timestamp: 1735600107955 - pypi: https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl name: mypy-extensions version: 1.0.0 diff --git a/pixi.toml b/pixi.toml index aeefdea6dacf..01f21c2b81fa 100644 --- a/pixi.toml +++ b/pixi.toml @@ -459,7 +459,7 @@ flatbuffers = ">=23" gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" jinja2 = ">=3.1.3,<3.2" # For `build_screenshot_compare.py` and other utilities that build websites. -mypy = "1.8.0" +mypy = "1.14.1" nasm = ">=2.16" # Required by https://github.com/memorysafety/rav1d for native video support ninja = "1.11.1" numpy = ">=1.23,<2" diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index 8b2e50bfa39a..9c5056e64c74 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -281,21 +281,11 @@ def __init__(self, data: T | None, strict: bool | None = None) -> None: self.pa_array = _empty_pa_array(self._ARROW_DATATYPE) @classmethod - def _required(cls, data: T | None) -> BaseBatch[T]: + def _converter(cls, data: T | None) -> BaseBatch[T] | None: """ - Primary method for creating Arrow arrays for optional components. + Primary method for creating Arrow arrays for components. - Just calls through to __init__, but with clearer type annotations. - """ - return cls(data) - - @classmethod - def _optional(cls, data: T | None) -> BaseBatch[T] | None: - """ - Primary method for creating Arrow arrays for optional components. - - For optional components, the default value of None is preserved in the field to indicate that the optional - field was not specified. + The default value of None is preserved in the field to indicate that the optional field was not specified. If any value other than None is provided, it is passed through to `__init__`. Parameters diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index da29c3817e22..8aa27d7a7a02 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -82,7 +82,7 @@ def __init__(self: Any, context: components.AnnotationContextLike): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - context=None, # type: ignore[arg-type] + context=None, ) @classmethod @@ -92,9 +92,53 @@ def _clear(cls) -> AnnotationContext: inst.__attrs_clear__() return inst - context: components.AnnotationContextBatch = field( - metadata={"component": "required"}, - converter=components.AnnotationContextBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + context: components.AnnotationContextLike | None = None, + ) -> AnnotationContext: + """ + Update only some specific fields of a `AnnotationContext`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + context: + List of class descriptions, mapping class indices to class names, colors etc. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "context": context, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AnnotationContext: + """Clear all the fields of a `AnnotationContext`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + context=[], + ) + return inst + + context: components.AnnotationContextBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.AnnotationContextBatch._converter, # type: ignore[misc] ) # List of class descriptions, mapping class indices to class names, colors etc. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index e31a9836628a..cfd1323ef72c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .arrows2d_ext import Arrows2DExt __all__ = ["Arrows2D"] @@ -57,14 +58,14 @@ class Arrows2D(Arrows2DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - vectors=None, # type: ignore[arg-type] - origins=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + vectors=None, + origins=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + draw_order=None, + class_ids=None, ) @classmethod @@ -74,18 +75,109 @@ def _clear(cls) -> Arrows2D: inst.__attrs_clear__() return inst - vectors: components.Vector2DBatch = field( - metadata={"component": "required"}, - converter=components.Vector2DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + vectors: datatypes.Vec2DArrayLike | None = None, + origins: datatypes.Vec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + draw_order: datatypes.Float32Like | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Arrows2D: + """ + Update only some specific fields of a `Arrows2D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + vectors: + All the vectors for each arrow in the batch. + origins: + All the origin (base) positions for each arrow in the batch. + + If no origins are set, (0, 0) is used as the origin for each arrow. + radii: + Optional radii for the arrows. + + The shaft is rendered as a line with `radius = 0.5 * radius`. + The tip is rendered with `height = 2.0 * radius` and `radius = 1.0 * radius`. + colors: + Optional colors for the points. + labels: + Optional text labels for the arrows. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "vectors": vectors, + "origins": origins, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "draw_order": draw_order, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Arrows2D: + """Clear all the fields of a `Arrows2D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + vectors=[], + origins=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + draw_order=[], + class_ids=[], + ) + return inst + + vectors: components.Vector2DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.Vector2DBatch._converter, # type: ignore[misc] ) # All the vectors for each arrow in the batch. # # (Docstring intentionally commented out to hide this field from the docs) origins: components.Position2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Position2DBatch._optional, # type: ignore[misc] + converter=components.Position2DBatch._converter, # type: ignore[misc] ) # All the origin (base) positions for each arrow in the batch. # @@ -94,9 +186,9 @@ def _clear(cls) -> Arrows2D: # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the arrows. # @@ -106,18 +198,18 @@ def _clear(cls) -> Arrows2D: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the points. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the arrows. # @@ -127,18 +219,18 @@ def _clear(cls) -> Arrows2D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # @@ -147,9 +239,9 @@ def _clear(cls) -> Arrows2D: # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the points. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index 282065177c60..576a461e992e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .arrows3d_ext import Arrows3DExt __all__ = ["Arrows3D"] @@ -57,13 +58,13 @@ class Arrows3D(Arrows3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - vectors=None, # type: ignore[arg-type] - origins=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + vectors=None, + origins=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + class_ids=None, ) @classmethod @@ -73,18 +74,102 @@ def _clear(cls) -> Arrows3D: inst.__attrs_clear__() return inst - vectors: components.Vector3DBatch = field( - metadata={"component": "required"}, - converter=components.Vector3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + vectors: datatypes.Vec3DArrayLike | None = None, + origins: datatypes.Vec3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Arrows3D: + """ + Update only some specific fields of a `Arrows3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + vectors: + All the vectors for each arrow in the batch. + origins: + All the origin (base) positions for each arrow in the batch. + + If no origins are set, (0, 0, 0) is used as the origin for each arrow. + radii: + Optional radii for the arrows. + + The shaft is rendered as a line with `radius = 0.5 * radius`. + The tip is rendered with `height = 2.0 * radius` and `radius = 1.0 * radius`. + colors: + Optional colors for the points. + labels: + Optional text labels for the arrows. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "vectors": vectors, + "origins": origins, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Arrows3D: + """Clear all the fields of a `Arrows3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + vectors=[], + origins=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + class_ids=[], + ) + return inst + + vectors: components.Vector3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.Vector3DBatch._converter, # type: ignore[misc] ) # All the vectors for each arrow in the batch. # # (Docstring intentionally commented out to hide this field from the docs) origins: components.Position3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Position3DBatch._optional, # type: ignore[misc] + converter=components.Position3DBatch._converter, # type: ignore[misc] ) # All the origin (base) positions for each arrow in the batch. # @@ -93,9 +178,9 @@ def _clear(cls) -> Arrows3D: # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the arrows. # @@ -105,18 +190,18 @@ def _clear(cls) -> Arrows3D: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the points. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the arrows. # @@ -126,18 +211,18 @@ def _clear(cls) -> Arrows3D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the points. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index 2f0d74c87bcc..eecdd926d70b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .asset3d_ext import Asset3DExt __all__ = ["Asset3D"] @@ -60,9 +61,9 @@ class Asset3D(Asset3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - blob=None, # type: ignore[arg-type] - media_type=None, # type: ignore[arg-type] - albedo_factor=None, # type: ignore[arg-type] + blob=None, + media_type=None, + albedo_factor=None, ) @classmethod @@ -72,18 +73,84 @@ def _clear(cls) -> Asset3D: inst.__attrs_clear__() return inst - blob: components.BlobBatch = field( - metadata={"component": "required"}, - converter=components.BlobBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + blob: datatypes.BlobLike | None = None, + media_type: datatypes.Utf8Like | None = None, + albedo_factor: datatypes.Rgba32Like | None = None, + ) -> Asset3D: + """ + Update only some specific fields of a `Asset3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + blob: + The asset's bytes. + media_type: + The Media Type of the asset. + + Supported values: + * `model/gltf-binary` + * `model/gltf+json` + * `model/obj` (.mtl material files are not supported yet, references are silently ignored) + * `model/stl` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + albedo_factor: + A color multiplier applied to the whole asset. + + For mesh who already have `albedo_factor` in materials, + it will be overwritten by actual `albedo_factor` of [`archetypes.Asset3D`][rerun.archetypes.Asset3D] (if specified). + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "blob": blob, + "media_type": media_type, + "albedo_factor": albedo_factor, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Asset3D: + """Clear all the fields of a `Asset3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + blob=[], + media_type=[], + albedo_factor=[], + ) + return inst + + blob: components.BlobBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.BlobBatch._converter, # type: ignore[misc] ) # The asset's bytes. # # (Docstring intentionally commented out to hide this field from the docs) media_type: components.MediaTypeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MediaTypeBatch._optional, # type: ignore[misc] + converter=components.MediaTypeBatch._converter, # type: ignore[misc] ) # The Media Type of the asset. # @@ -99,9 +166,9 @@ def _clear(cls) -> Asset3D: # (Docstring intentionally commented out to hide this field from the docs) albedo_factor: components.AlbedoFactorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AlbedoFactorBatch._optional, # type: ignore[misc] + converter=components.AlbedoFactorBatch._converter, # type: ignore[misc] ) # A color multiplier applied to the whole asset. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index f78337f6e421..23b4c55968e2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .asset_video_ext import AssetVideoExt __all__ = ["AssetVideo"] @@ -117,8 +118,8 @@ class AssetVideo(AssetVideoExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - blob=None, # type: ignore[arg-type] - media_type=None, # type: ignore[arg-type] + blob=None, + media_type=None, ) @classmethod @@ -128,18 +129,73 @@ def _clear(cls) -> AssetVideo: inst.__attrs_clear__() return inst - blob: components.BlobBatch = field( - metadata={"component": "required"}, - converter=components.BlobBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + blob: datatypes.BlobLike | None = None, + media_type: datatypes.Utf8Like | None = None, + ) -> AssetVideo: + """ + Update only some specific fields of a `AssetVideo`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + blob: + The asset's bytes. + media_type: + The Media Type of the asset. + + Supported values: + * `video/mp4` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "blob": blob, + "media_type": media_type, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AssetVideo: + """Clear all the fields of a `AssetVideo`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + blob=[], + media_type=[], + ) + return inst + + blob: components.BlobBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.BlobBatch._converter, # type: ignore[misc] ) # The asset's bytes. # # (Docstring intentionally commented out to hide this field from the docs) media_type: components.MediaTypeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MediaTypeBatch._optional, # type: ignore[misc] + converter=components.MediaTypeBatch._converter, # type: ignore[misc] ) # The Media Type of the asset. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py index f7951e40d071..d6f211e046c4 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py @@ -69,8 +69,8 @@ def __init__(self: Any, values: datatypes.TensorDataLike, *, color: datatypes.Rg def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - values=None, # type: ignore[arg-type] - color=None, # type: ignore[arg-type] + values=None, + color=None, ) @classmethod @@ -80,8 +80,57 @@ def _clear(cls) -> BarChart: inst.__attrs_clear__() return inst - values: components.TensorDataBatch = field( - metadata={"component": "required"}, + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + values: datatypes.TensorDataLike | None = None, + color: datatypes.Rgba32Like | None = None, + ) -> BarChart: + """ + Update only some specific fields of a `BarChart`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + values: + The values. Should always be a 1-dimensional tensor (i.e. a vector). + color: + The color of the bar chart + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "values": values, + "color": color, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> BarChart: + """Clear all the fields of a `BarChart`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + values=[], + color=[], + ) + return inst + + values: components.TensorDataBatch | None = field( + metadata={"component": True}, + default=None, converter=BarChartExt.values__field_converter_override, # type: ignore[misc] ) # The values. Should always be a 1-dimensional tensor (i.e. a vector). @@ -89,9 +138,9 @@ def _clear(cls) -> BarChart: # (Docstring intentionally commented out to hide this field from the docs) color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # The color of the bar chart # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index 1e22d23e0e2f..651f1bb79725 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .boxes2d_ext import Boxes2DExt __all__ = ["Boxes2D"] @@ -48,14 +49,14 @@ class Boxes2D(Boxes2DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - half_sizes=None, # type: ignore[arg-type] - centers=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + half_sizes=None, + centers=None, + colors=None, + radii=None, + labels=None, + show_labels=None, + draw_order=None, + class_ids=None, ) @classmethod @@ -65,45 +66,133 @@ def _clear(cls) -> Boxes2D: inst.__attrs_clear__() return inst - half_sizes: components.HalfSize2DBatch = field( - metadata={"component": "required"}, - converter=components.HalfSize2DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + half_sizes: datatypes.Vec2DArrayLike | None = None, + centers: datatypes.Vec2DArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + draw_order: datatypes.Float32Like | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Boxes2D: + """ + Update only some specific fields of a `Boxes2D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + half_sizes: + All half-extents that make up the batch of boxes. + centers: + Optional center positions of the boxes. + colors: + Optional colors for the boxes. + radii: + Optional radii for the lines that make up the boxes. + labels: + Optional text labels for the boxes. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + The default for 2D boxes is 10.0. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "half_sizes": half_sizes, + "centers": centers, + "colors": colors, + "radii": radii, + "labels": labels, + "show_labels": show_labels, + "draw_order": draw_order, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Boxes2D: + """Clear all the fields of a `Boxes2D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + half_sizes=[], + centers=[], + colors=[], + radii=[], + labels=[], + show_labels=[], + draw_order=[], + class_ids=[], + ) + return inst + + half_sizes: components.HalfSize2DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.HalfSize2DBatch._converter, # type: ignore[misc] ) # All half-extents that make up the batch of boxes. # # (Docstring intentionally commented out to hide this field from the docs) centers: components.Position2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Position2DBatch._optional, # type: ignore[misc] + converter=components.Position2DBatch._converter, # type: ignore[misc] ) # Optional center positions of the boxes. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the boxes. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the lines that make up the boxes. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the boxes. # @@ -113,18 +202,18 @@ def _clear(cls) -> Boxes2D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # @@ -135,9 +224,9 @@ def _clear(cls) -> Boxes2D: # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index ff33da0d72a1..a600bbcad191 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .boxes3d_ext import Boxes3DExt __all__ = ["Boxes3D"] @@ -66,16 +67,16 @@ class Boxes3D(Boxes3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - half_sizes=None, # type: ignore[arg-type] - centers=None, # type: ignore[arg-type] - rotation_axis_angles=None, # type: ignore[arg-type] - quaternions=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - fill_mode=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + half_sizes=None, + centers=None, + rotation_axis_angles=None, + quaternions=None, + colors=None, + radii=None, + fill_mode=None, + labels=None, + show_labels=None, + class_ids=None, ) @classmethod @@ -85,18 +86,121 @@ def _clear(cls) -> Boxes3D: inst.__attrs_clear__() return inst - half_sizes: components.HalfSize3DBatch = field( - metadata={"component": "required"}, - converter=components.HalfSize3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + half_sizes: datatypes.Vec3DArrayLike | None = None, + centers: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + fill_mode: components.FillModeLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Boxes3D: + """ + Update only some specific fields of a `Boxes3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + half_sizes: + All half-extents that make up the batch of boxes. + centers: + Optional center positions of the boxes. + + If not specified, the centers will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the axes of the boxes align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the axes of the boxes align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the boxes. + radii: + Optional radii for the lines that make up the boxes. + fill_mode: + Optionally choose whether the boxes are drawn with lines or solid. + labels: + Optional text labels for the boxes. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "half_sizes": half_sizes, + "centers": centers, + "rotation_axis_angles": rotation_axis_angles, + "quaternions": quaternions, + "colors": colors, + "radii": radii, + "fill_mode": fill_mode, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Boxes3D: + """Clear all the fields of a `Boxes3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + half_sizes=[], + centers=[], + rotation_axis_angles=[], + quaternions=[], + colors=[], + radii=[], + fill_mode=[], + labels=[], + show_labels=[], + class_ids=[], + ) + return inst + + half_sizes: components.HalfSize3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.HalfSize3DBatch._converter, # type: ignore[misc] ) # All half-extents that make up the batch of boxes. # # (Docstring intentionally commented out to hide this field from the docs) centers: components.PoseTranslation3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseTranslation3DBatch._optional, # type: ignore[misc] + converter=components.PoseTranslation3DBatch._converter, # type: ignore[misc] ) # Optional center positions of the boxes. # @@ -106,9 +210,9 @@ def _clear(cls) -> Boxes3D: # (Docstring intentionally commented out to hide this field from the docs) rotation_axis_angles: components.PoseRotationAxisAngleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationAxisAngleBatch._optional, # type: ignore[misc] + converter=components.PoseRotationAxisAngleBatch._converter, # type: ignore[misc] ) # Rotations via axis + angle. # @@ -118,9 +222,9 @@ def _clear(cls) -> Boxes3D: # (Docstring intentionally commented out to hide this field from the docs) quaternions: components.PoseRotationQuatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationQuatBatch._optional, # type: ignore[misc] + converter=components.PoseRotationQuatBatch._converter, # type: ignore[misc] ) # Rotations via quaternion. # @@ -130,36 +234,36 @@ def _clear(cls) -> Boxes3D: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the boxes. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the lines that make up the boxes. # # (Docstring intentionally commented out to hide this field from the docs) fill_mode: components.FillModeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.FillModeBatch._optional, # type: ignore[misc] + converter=components.FillModeBatch._converter, # type: ignore[misc] ) # Optionally choose whether the boxes are drawn with lines or solid. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the boxes. # @@ -169,18 +273,18 @@ def _clear(cls) -> Boxes3D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional [`components.ClassId`][rerun.components.ClassId]s for the boxes. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py index 88516b702c89..798ea93dd751 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .capsules3d_ext import Capsules3DExt __all__ = ["Capsules3D"] @@ -80,15 +81,15 @@ class Capsules3D(Capsules3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - lengths=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - translations=None, # type: ignore[arg-type] - rotation_axis_angles=None, # type: ignore[arg-type] - quaternions=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + lengths=None, + radii=None, + translations=None, + rotation_axis_angles=None, + quaternions=None, + colors=None, + labels=None, + show_labels=None, + class_ids=None, ) @classmethod @@ -98,26 +99,122 @@ def _clear(cls) -> Capsules3D: inst.__attrs_clear__() return inst - lengths: components.LengthBatch = field( - metadata={"component": "required"}, - converter=components.LengthBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + lengths: datatypes.Float32ArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + translations: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Capsules3D: + """ + Update only some specific fields of a `Capsules3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + lengths: + Lengths of the capsules, defined as the distance between the centers of the endcaps. + radii: + Radii of the capsules. + translations: + Optional translations of the capsules. + + If not specified, one end of each capsule will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the capsules align with the +Z axis of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the capsules align with the +Z axis of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the capsules. + labels: + Optional text labels for the capsules, which will be located at their centers. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class ID for the ellipsoids. + + The class ID provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "lengths": lengths, + "radii": radii, + "translations": translations, + "rotation_axis_angles": rotation_axis_angles, + "quaternions": quaternions, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Capsules3D: + """Clear all the fields of a `Capsules3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + lengths=[], + radii=[], + translations=[], + rotation_axis_angles=[], + quaternions=[], + colors=[], + labels=[], + show_labels=[], + class_ids=[], + ) + return inst + + lengths: components.LengthBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.LengthBatch._converter, # type: ignore[misc] ) # Lengths of the capsules, defined as the distance between the centers of the endcaps. # # (Docstring intentionally commented out to hide this field from the docs) - radii: components.RadiusBatch = field( - metadata={"component": "required"}, - converter=components.RadiusBatch._required, # type: ignore[misc] + radii: components.RadiusBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Radii of the capsules. # # (Docstring intentionally commented out to hide this field from the docs) translations: components.PoseTranslation3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseTranslation3DBatch._optional, # type: ignore[misc] + converter=components.PoseTranslation3DBatch._converter, # type: ignore[misc] ) # Optional translations of the capsules. # @@ -127,9 +224,9 @@ def _clear(cls) -> Capsules3D: # (Docstring intentionally commented out to hide this field from the docs) rotation_axis_angles: components.PoseRotationAxisAngleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationAxisAngleBatch._optional, # type: ignore[misc] + converter=components.PoseRotationAxisAngleBatch._converter, # type: ignore[misc] ) # Rotations via axis + angle. # @@ -139,9 +236,9 @@ def _clear(cls) -> Capsules3D: # (Docstring intentionally commented out to hide this field from the docs) quaternions: components.PoseRotationQuatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationQuatBatch._optional, # type: ignore[misc] + converter=components.PoseRotationQuatBatch._converter, # type: ignore[misc] ) # Rotations via quaternion. # @@ -151,36 +248,36 @@ def _clear(cls) -> Capsules3D: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the capsules. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the capsules, which will be located at their centers. # # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class ID for the ellipsoids. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/clear.py b/rerun_py/rerun_sdk/rerun/archetypes/clear.py index 47c13e4383e3..24f9d45ab594 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/clear.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/clear.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .clear_ext import ClearExt __all__ = ["Clear"] @@ -68,7 +69,7 @@ class Clear(ClearExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - is_recursive=None, # type: ignore[arg-type] + is_recursive=None, ) @classmethod @@ -78,9 +79,43 @@ def _clear(cls) -> Clear: inst.__attrs_clear__() return inst - is_recursive: components.ClearIsRecursiveBatch = field( - metadata={"component": "required"}, - converter=components.ClearIsRecursiveBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + is_recursive: datatypes.BoolLike | None = None, + ) -> Clear: + """Update only some specific fields of a `Clear`.""" + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "is_recursive": is_recursive, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Clear: + """Clear all the fields of a `Clear`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + is_recursive=[], + ) + return inst + + is_recursive: components.ClearIsRecursiveBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ClearIsRecursiveBatch._converter, # type: ignore[misc] ) __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py index 5fc1d1ed023c..a357abff9aa1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .depth_image_ext import DepthImageExt __all__ = ["DepthImage"] @@ -66,13 +67,13 @@ class DepthImage(DepthImageExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - buffer=None, # type: ignore[arg-type] - format=None, # type: ignore[arg-type] - meter=None, # type: ignore[arg-type] - colormap=None, # type: ignore[arg-type] - depth_range=None, # type: ignore[arg-type] - point_fill_ratio=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] + buffer=None, + format=None, + meter=None, + colormap=None, + depth_range=None, + point_fill_ratio=None, + draw_order=None, ) @classmethod @@ -82,26 +83,127 @@ def _clear(cls) -> DepthImage: inst.__attrs_clear__() return inst - buffer: components.ImageBufferBatch = field( - metadata={"component": "required"}, - converter=components.ImageBufferBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + buffer: datatypes.BlobLike | None = None, + format: datatypes.ImageFormatLike | None = None, + meter: datatypes.Float32Like | None = None, + colormap: components.ColormapLike | None = None, + depth_range: datatypes.Range1DLike | None = None, + point_fill_ratio: datatypes.Float32Like | None = None, + draw_order: datatypes.Float32Like | None = None, + ) -> DepthImage: + """ + Update only some specific fields of a `DepthImage`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + buffer: + The raw depth image data. + format: + The format of the image. + meter: + An optional floating point value that specifies how long a meter is in the native depth units. + + For instance: with uint16, perhaps meter=1000 which would mean you have millimeter precision + and a range of up to ~65 meters (2^16 / 1000). + + Note that the only effect on 2D views is the physical depth values shown when hovering the image. + In 3D views on the other hand, this affects where the points of the point cloud are placed. + colormap: + Colormap to use for rendering the depth image. + + If not set, the depth image will be rendered using the Turbo colormap. + depth_range: + The expected range of depth values. + + This is typically the expected range of valid values. + Everything outside of the range is clamped to the range for the purpose of colormpaping. + Note that point clouds generated from this image will still display all points, regardless of this range. + + If not specified, the range will be automatically estimated from the data. + Note that the Viewer may try to guess a wider range than the minimum/maximum of values + in the contents of the depth image. + E.g. if all values are positive, some bigger than 1.0 and all smaller than 255.0, + the Viewer will guess that the data likely came from an 8bit image, thus assuming a range of 0-255. + point_fill_ratio: + Scale the radii of the points in the point cloud generated from this image. + + A fill ratio of 1.0 (the default) means that each point is as big as to touch the center of its neighbor + if it is at the same depth, leaving no gaps. + A fill ratio of 0.5 means that each point touches the edge of its neighbor if it has the same depth. + + TODO(#6744): This applies only to 3D views! + draw_order: + An optional floating point value that specifies the 2D drawing order, used only if the depth image is shown as a 2D image. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "buffer": buffer, + "format": format, + "meter": meter, + "colormap": colormap, + "depth_range": depth_range, + "point_fill_ratio": point_fill_ratio, + "draw_order": draw_order, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> DepthImage: + """Clear all the fields of a `DepthImage`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + buffer=[], + format=[], + meter=[], + colormap=[], + depth_range=[], + point_fill_ratio=[], + draw_order=[], + ) + return inst + + buffer: components.ImageBufferBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageBufferBatch._converter, # type: ignore[misc] ) # The raw depth image data. # # (Docstring intentionally commented out to hide this field from the docs) - format: components.ImageFormatBatch = field( - metadata={"component": "required"}, - converter=components.ImageFormatBatch._required, # type: ignore[misc] + format: components.ImageFormatBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageFormatBatch._converter, # type: ignore[misc] ) # The format of the image. # # (Docstring intentionally commented out to hide this field from the docs) meter: components.DepthMeterBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DepthMeterBatch._optional, # type: ignore[misc] + converter=components.DepthMeterBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies how long a meter is in the native depth units. # @@ -114,9 +216,9 @@ def _clear(cls) -> DepthImage: # (Docstring intentionally commented out to hide this field from the docs) colormap: components.ColormapBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColormapBatch._optional, # type: ignore[misc] + converter=components.ColormapBatch._converter, # type: ignore[misc] ) # Colormap to use for rendering the depth image. # @@ -125,9 +227,9 @@ def _clear(cls) -> DepthImage: # (Docstring intentionally commented out to hide this field from the docs) depth_range: components.ValueRangeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ValueRangeBatch._optional, # type: ignore[misc] + converter=components.ValueRangeBatch._converter, # type: ignore[misc] ) # The expected range of depth values. # @@ -144,9 +246,9 @@ def _clear(cls) -> DepthImage: # (Docstring intentionally commented out to hide this field from the docs) point_fill_ratio: components.FillRatioBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.FillRatioBatch._optional, # type: ignore[misc] + converter=components.FillRatioBatch._converter, # type: ignore[misc] ) # Scale the radii of the points in the point cloud generated from this image. # @@ -159,9 +261,9 @@ def _clear(cls) -> DepthImage: # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order, used only if the depth image is shown as a 2D image. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index d96015a93802..fa001fc3f920 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .ellipsoids3d_ext import Ellipsoids3DExt __all__ = ["Ellipsoids3D"] @@ -69,16 +70,16 @@ class Ellipsoids3D(Ellipsoids3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - half_sizes=None, # type: ignore[arg-type] - centers=None, # type: ignore[arg-type] - rotation_axis_angles=None, # type: ignore[arg-type] - quaternions=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - line_radii=None, # type: ignore[arg-type] - fill_mode=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + half_sizes=None, + centers=None, + rotation_axis_angles=None, + quaternions=None, + colors=None, + line_radii=None, + fill_mode=None, + labels=None, + show_labels=None, + class_ids=None, ) @classmethod @@ -88,9 +89,111 @@ def _clear(cls) -> Ellipsoids3D: inst.__attrs_clear__() return inst - half_sizes: components.HalfSize3DBatch = field( - metadata={"component": "required"}, - converter=components.HalfSize3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + half_sizes: datatypes.Vec3DArrayLike | None = None, + centers: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + line_radii: datatypes.Float32ArrayLike | None = None, + fill_mode: components.FillModeLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Ellipsoids3D: + """ + Update only some specific fields of a `Ellipsoids3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + half_sizes: + For each ellipsoid, half of its size on its three axes. + + If all components are equal, then it is a sphere with that radius. + centers: + Optional center positions of the ellipsoids. + + If not specified, the centers will be at (0, 0, 0). + Note that this uses a [`components.PoseTranslation3D`][rerun.components.PoseTranslation3D] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + rotation_axis_angles: + Rotations via axis + angle. + + If no rotation is specified, the axes of the ellipsoid align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationAxisAngle`][rerun.components.PoseRotationAxisAngle] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + quaternions: + Rotations via quaternion. + + If no rotation is specified, the axes of the ellipsoid align with the axes of the local coordinate system. + Note that this uses a [`components.PoseRotationQuat`][rerun.components.PoseRotationQuat] which is also used by [`archetypes.InstancePoses3D`][rerun.archetypes.InstancePoses3D]. + colors: + Optional colors for the ellipsoids. + line_radii: + Optional radii for the lines used when the ellipsoid is rendered as a wireframe. + fill_mode: + Optionally choose whether the ellipsoids are drawn with lines or solid. + labels: + Optional text labels for the ellipsoids. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class ID for the ellipsoids. + + The class ID provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "half_sizes": half_sizes, + "centers": centers, + "rotation_axis_angles": rotation_axis_angles, + "quaternions": quaternions, + "colors": colors, + "line_radii": line_radii, + "fill_mode": fill_mode, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Ellipsoids3D: + """Clear all the fields of a `Ellipsoids3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + half_sizes=[], + centers=[], + rotation_axis_angles=[], + quaternions=[], + colors=[], + line_radii=[], + fill_mode=[], + labels=[], + show_labels=[], + class_ids=[], + ) + return inst + + half_sizes: components.HalfSize3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.HalfSize3DBatch._converter, # type: ignore[misc] ) # For each ellipsoid, half of its size on its three axes. # @@ -99,9 +202,9 @@ def _clear(cls) -> Ellipsoids3D: # (Docstring intentionally commented out to hide this field from the docs) centers: components.PoseTranslation3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseTranslation3DBatch._optional, # type: ignore[misc] + converter=components.PoseTranslation3DBatch._converter, # type: ignore[misc] ) # Optional center positions of the ellipsoids. # @@ -111,9 +214,9 @@ def _clear(cls) -> Ellipsoids3D: # (Docstring intentionally commented out to hide this field from the docs) rotation_axis_angles: components.PoseRotationAxisAngleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationAxisAngleBatch._optional, # type: ignore[misc] + converter=components.PoseRotationAxisAngleBatch._converter, # type: ignore[misc] ) # Rotations via axis + angle. # @@ -123,9 +226,9 @@ def _clear(cls) -> Ellipsoids3D: # (Docstring intentionally commented out to hide this field from the docs) quaternions: components.PoseRotationQuatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationQuatBatch._optional, # type: ignore[misc] + converter=components.PoseRotationQuatBatch._converter, # type: ignore[misc] ) # Rotations via quaternion. # @@ -135,54 +238,54 @@ def _clear(cls) -> Ellipsoids3D: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the ellipsoids. # # (Docstring intentionally commented out to hide this field from the docs) line_radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the lines used when the ellipsoid is rendered as a wireframe. # # (Docstring intentionally commented out to hide this field from the docs) fill_mode: components.FillModeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.FillModeBatch._optional, # type: ignore[misc] + converter=components.FillModeBatch._converter, # type: ignore[misc] ) # Optionally choose whether the ellipsoids are drawn with lines or solid. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the ellipsoids. # # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class ID for the ellipsoids. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py index 8cc606648010..290025516502 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .encoded_image_ext import EncodedImageExt __all__ = ["EncodedImage"] @@ -48,10 +49,10 @@ class EncodedImage(EncodedImageExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - blob=None, # type: ignore[arg-type] - media_type=None, # type: ignore[arg-type] - opacity=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] + blob=None, + media_type=None, + opacity=None, + draw_order=None, ) @classmethod @@ -61,18 +62,88 @@ def _clear(cls) -> EncodedImage: inst.__attrs_clear__() return inst - blob: components.BlobBatch = field( - metadata={"component": "required"}, - converter=components.BlobBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + blob: datatypes.BlobLike | None = None, + media_type: datatypes.Utf8Like | None = None, + opacity: datatypes.Float32Like | None = None, + draw_order: datatypes.Float32Like | None = None, + ) -> EncodedImage: + """ + Update only some specific fields of a `EncodedImage`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + blob: + The encoded content of some image file, e.g. a PNG or JPEG. + media_type: + The Media Type of the asset. + + Supported values: + * `image/jpeg` + * `image/png` + + If omitted, the viewer will try to guess from the data blob. + If it cannot guess, it won't be able to render the asset. + opacity: + Opacity of the image, useful for layering several images. + + Defaults to 1.0 (fully opaque). + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "blob": blob, + "media_type": media_type, + "opacity": opacity, + "draw_order": draw_order, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> EncodedImage: + """Clear all the fields of a `EncodedImage`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + blob=[], + media_type=[], + opacity=[], + draw_order=[], + ) + return inst + + blob: components.BlobBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.BlobBatch._converter, # type: ignore[misc] ) # The encoded content of some image file, e.g. a PNG or JPEG. # # (Docstring intentionally commented out to hide this field from the docs) media_type: components.MediaTypeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MediaTypeBatch._optional, # type: ignore[misc] + converter=components.MediaTypeBatch._converter, # type: ignore[misc] ) # The Media Type of the asset. # @@ -86,9 +157,9 @@ def _clear(cls) -> EncodedImage: # (Docstring intentionally commented out to hide this field from the docs) opacity: components.OpacityBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.OpacityBatch._optional, # type: ignore[misc] + converter=components.OpacityBatch._converter, # type: ignore[misc] ) # Opacity of the image, useful for layering several images. # @@ -97,9 +168,9 @@ def _clear(cls) -> EncodedImage: # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py index 4e79737a229b..56a9c1d78513 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .geo_line_strings_ext import GeoLineStringsExt __all__ = ["GeoLineStrings"] @@ -63,9 +64,9 @@ class GeoLineStrings(GeoLineStringsExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - line_strings=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] + line_strings=None, + radii=None, + colors=None, ) @classmethod @@ -75,18 +76,78 @@ def _clear(cls) -> GeoLineStrings: inst.__attrs_clear__() return inst - line_strings: components.GeoLineStringBatch = field( - metadata={"component": "required"}, - converter=components.GeoLineStringBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + line_strings: components.GeoLineStringArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + ) -> GeoLineStrings: + """ + Update only some specific fields of a `GeoLineStrings`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + line_strings: + The line strings, expressed in [EPSG:4326](https://epsg.io/4326) coordinates (North/East-positive degrees). + radii: + Optional radii for the line strings. + + *Note*: scene units radiii are interpreted as meters. Currently, the display scale only considers the latitude of + the first vertex of each line string (see [this issue](https://github.com/rerun-io/rerun/issues/8013)). + colors: + Optional colors for the line strings. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "line_strings": line_strings, + "radii": radii, + "colors": colors, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> GeoLineStrings: + """Clear all the fields of a `GeoLineStrings`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + line_strings=[], + radii=[], + colors=[], + ) + return inst + + line_strings: components.GeoLineStringBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.GeoLineStringBatch._converter, # type: ignore[misc] ) # The line strings, expressed in [EPSG:4326](https://epsg.io/4326) coordinates (North/East-positive degrees). # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the line strings. # @@ -96,9 +157,9 @@ def _clear(cls) -> GeoLineStrings: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the line strings. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py index bb707e903c4c..024a8332c32e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .geo_points_ext import GeoPointsExt __all__ = ["GeoPoints"] @@ -55,10 +56,10 @@ class GeoPoints(GeoPointsExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - positions=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + positions=None, + radii=None, + colors=None, + class_ids=None, ) @classmethod @@ -68,18 +69,84 @@ def _clear(cls) -> GeoPoints: inst.__attrs_clear__() return inst - positions: components.LatLonBatch = field( - metadata={"component": "required"}, - converter=components.LatLonBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + positions: datatypes.DVec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> GeoPoints: + """ + Update only some specific fields of a `GeoPoints`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + positions: + The [EPSG:4326](https://epsg.io/4326) coordinates for the points (North/East-positive degrees). + radii: + Optional radii for the points, effectively turning them into circles. + + *Note*: scene units radiii are interpreted as meters. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "positions": positions, + "radii": radii, + "colors": colors, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> GeoPoints: + """Clear all the fields of a `GeoPoints`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + positions=[], + radii=[], + colors=[], + class_ids=[], + ) + return inst + + positions: components.LatLonBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.LatLonBatch._converter, # type: ignore[misc] ) # The [EPSG:4326](https://epsg.io/4326) coordinates for the points (North/East-positive degrees). # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the points, effectively turning them into circles. # @@ -88,9 +155,9 @@ def _clear(cls) -> GeoPoints: # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the points. # @@ -100,9 +167,9 @@ def _clear(cls) -> GeoPoints: # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the points. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index 9cc648521d64..fd89ff88fa56 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -77,8 +77,8 @@ def __init__(self: Any, edges: datatypes.Utf8PairArrayLike, *, graph_type: compo def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - edges=None, # type: ignore[arg-type] - graph_type=None, # type: ignore[arg-type] + edges=None, + graph_type=None, ) @classmethod @@ -88,18 +88,69 @@ def _clear(cls) -> GraphEdges: inst.__attrs_clear__() return inst - edges: components.GraphEdgeBatch = field( - metadata={"component": "required"}, - converter=components.GraphEdgeBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + edges: datatypes.Utf8PairArrayLike | None = None, + graph_type: components.GraphTypeLike | None = None, + ) -> GraphEdges: + """ + Update only some specific fields of a `GraphEdges`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + edges: + A list of node tuples. + graph_type: + Specifies if the graph is directed or undirected. + + If no [`components.GraphType`][rerun.components.GraphType] is provided, the graph is assumed to be undirected. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "edges": edges, + "graph_type": graph_type, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> GraphEdges: + """Clear all the fields of a `GraphEdges`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + edges=[], + graph_type=[], + ) + return inst + + edges: components.GraphEdgeBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.GraphEdgeBatch._converter, # type: ignore[misc] ) # A list of node tuples. # # (Docstring intentionally commented out to hide this field from the docs) graph_type: components.GraphTypeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.GraphTypeBatch._optional, # type: ignore[misc] + converter=components.GraphTypeBatch._converter, # type: ignore[misc] ) # Specifies if the graph is directed or undirected. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index ad23e270e2dc..9e3f77b69065 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -97,12 +97,12 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - node_ids=None, # type: ignore[arg-type] - positions=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] + node_ids=None, + positions=None, + colors=None, + labels=None, + show_labels=None, + radii=None, ) @classmethod @@ -112,54 +112,123 @@ def _clear(cls) -> GraphNodes: inst.__attrs_clear__() return inst - node_ids: components.GraphNodeBatch = field( - metadata={"component": "required"}, - converter=components.GraphNodeBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + node_ids: datatypes.Utf8ArrayLike | None = None, + positions: datatypes.Vec2DArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + ) -> GraphNodes: + """ + Update only some specific fields of a `GraphNodes`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + node_ids: + A list of node IDs. + positions: + Optional center positions of the nodes. + colors: + Optional colors for the boxes. + labels: + Optional text labels for the node. + show_labels: + Optional choice of whether the text labels should be shown by default. + radii: + Optional radii for nodes. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "node_ids": node_ids, + "positions": positions, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "radii": radii, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> GraphNodes: + """Clear all the fields of a `GraphNodes`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + node_ids=[], + positions=[], + colors=[], + labels=[], + show_labels=[], + radii=[], + ) + return inst + + node_ids: components.GraphNodeBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.GraphNodeBatch._converter, # type: ignore[misc] ) # A list of node IDs. # # (Docstring intentionally commented out to hide this field from the docs) positions: components.Position2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Position2DBatch._optional, # type: ignore[misc] + converter=components.Position2DBatch._converter, # type: ignore[misc] ) # Optional center positions of the nodes. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the boxes. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the node. # # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for nodes. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index c0cfb2703d40..de908e7840ea 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .image_ext import ImageExt __all__ = ["Image"] @@ -92,10 +93,10 @@ class Image(ImageExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - buffer=None, # type: ignore[arg-type] - format=None, # type: ignore[arg-type] - opacity=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] + buffer=None, + format=None, + opacity=None, + draw_order=None, ) @classmethod @@ -105,26 +106,90 @@ def _clear(cls) -> Image: inst.__attrs_clear__() return inst - buffer: components.ImageBufferBatch = field( - metadata={"component": "required"}, - converter=components.ImageBufferBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + buffer: datatypes.BlobLike | None = None, + format: datatypes.ImageFormatLike | None = None, + opacity: datatypes.Float32Like | None = None, + draw_order: datatypes.Float32Like | None = None, + ) -> Image: + """ + Update only some specific fields of a `Image`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + buffer: + The raw image data. + format: + The format of the image. + opacity: + Opacity of the image, useful for layering several images. + + Defaults to 1.0 (fully opaque). + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "buffer": buffer, + "format": format, + "opacity": opacity, + "draw_order": draw_order, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Image: + """Clear all the fields of a `Image`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + buffer=[], + format=[], + opacity=[], + draw_order=[], + ) + return inst + + buffer: components.ImageBufferBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageBufferBatch._converter, # type: ignore[misc] ) # The raw image data. # # (Docstring intentionally commented out to hide this field from the docs) - format: components.ImageFormatBatch = field( - metadata={"component": "required"}, - converter=components.ImageFormatBatch._required, # type: ignore[misc] + format: components.ImageFormatBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageFormatBatch._converter, # type: ignore[misc] ) # The format of the image. # # (Docstring intentionally commented out to hide this field from the docs) opacity: components.OpacityBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.OpacityBatch._optional, # type: ignore[misc] + converter=components.OpacityBatch._converter, # type: ignore[misc] ) # Opacity of the image, useful for layering several images. # @@ -133,9 +198,9 @@ def _clear(cls) -> Image: # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py index 0532c2968c76..146e397d8b9b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py @@ -114,11 +114,11 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - translations=None, # type: ignore[arg-type] - rotation_axis_angles=None, # type: ignore[arg-type] - quaternions=None, # type: ignore[arg-type] - scales=None, # type: ignore[arg-type] - mat3x3=None, # type: ignore[arg-type] + translations=None, + rotation_axis_angles=None, + quaternions=None, + scales=None, + mat3x3=None, ) @classmethod @@ -128,46 +128,109 @@ def _clear(cls) -> InstancePoses3D: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + translations: datatypes.Vec3DArrayLike | None = None, + rotation_axis_angles: datatypes.RotationAxisAngleArrayLike | None = None, + quaternions: datatypes.QuaternionArrayLike | None = None, + scales: datatypes.Vec3DArrayLike | None = None, + mat3x3: datatypes.Mat3x3ArrayLike | None = None, + ) -> InstancePoses3D: + """ + Update only some specific fields of a `InstancePoses3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + translations: + Translation vectors. + rotation_axis_angles: + Rotations via axis + angle. + quaternions: + Rotations via quaternion. + scales: + Scaling factors. + mat3x3: + 3x3 transformation matrices. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "translations": translations, + "rotation_axis_angles": rotation_axis_angles, + "quaternions": quaternions, + "scales": scales, + "mat3x3": mat3x3, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> InstancePoses3D: + """Clear all the fields of a `InstancePoses3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + translations=[], + rotation_axis_angles=[], + quaternions=[], + scales=[], + mat3x3=[], + ) + return inst + translations: components.PoseTranslation3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseTranslation3DBatch._optional, # type: ignore[misc] + converter=components.PoseTranslation3DBatch._converter, # type: ignore[misc] ) # Translation vectors. # # (Docstring intentionally commented out to hide this field from the docs) rotation_axis_angles: components.PoseRotationAxisAngleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationAxisAngleBatch._optional, # type: ignore[misc] + converter=components.PoseRotationAxisAngleBatch._converter, # type: ignore[misc] ) # Rotations via axis + angle. # # (Docstring intentionally commented out to hide this field from the docs) quaternions: components.PoseRotationQuatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseRotationQuatBatch._optional, # type: ignore[misc] + converter=components.PoseRotationQuatBatch._converter, # type: ignore[misc] ) # Rotations via quaternion. # # (Docstring intentionally commented out to hide this field from the docs) scales: components.PoseScale3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseScale3DBatch._optional, # type: ignore[misc] + converter=components.PoseScale3DBatch._converter, # type: ignore[misc] ) # Scaling factors. # # (Docstring intentionally commented out to hide this field from the docs) mat3x3: components.PoseTransformMat3x3Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.PoseTransformMat3x3Batch._optional, # type: ignore[misc] + converter=components.PoseTransformMat3x3Batch._converter, # type: ignore[misc] ) # 3x3 transformation matrices. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 89891b327415..6f48d660b8c5 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -154,13 +154,13 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - strips=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + strips=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + draw_order=None, + class_ids=None, ) @classmethod @@ -170,36 +170,117 @@ def _clear(cls) -> LineStrips2D: inst.__attrs_clear__() return inst - strips: components.LineStrip2DBatch = field( - metadata={"component": "required"}, - converter=components.LineStrip2DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + strips: components.LineStrip2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + draw_order: datatypes.Float32Like | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> LineStrips2D: + """ + Update only some specific fields of a `LineStrips2D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + strips: + All the actual 2D line strips that make up the batch. + radii: + Optional radii for the line strips. + colors: + Optional colors for the line strips. + labels: + Optional text labels for the line strips. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order of each line strip. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "strips": strips, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "draw_order": draw_order, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> LineStrips2D: + """Clear all the fields of a `LineStrips2D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + strips=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + draw_order=[], + class_ids=[], + ) + return inst + + strips: components.LineStrip2DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.LineStrip2DBatch._converter, # type: ignore[misc] ) # All the actual 2D line strips that make up the batch. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the line strips. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the line strips. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the line strips. # @@ -209,18 +290,18 @@ def _clear(cls) -> LineStrips2D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order of each line strip. # @@ -229,9 +310,9 @@ def _clear(cls) -> LineStrips2D: # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py index 36d6e2e164df..0ed372d2c377 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py @@ -158,12 +158,12 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - strips=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + strips=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + class_ids=None, ) @classmethod @@ -173,36 +173,110 @@ def _clear(cls) -> LineStrips3D: inst.__attrs_clear__() return inst - strips: components.LineStrip3DBatch = field( - metadata={"component": "required"}, - converter=components.LineStrip3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + strips: components.LineStrip3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> LineStrips3D: + """ + Update only some specific fields of a `LineStrips3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + strips: + All the actual 3D line strips that make up the batch. + radii: + Optional radii for the line strips. + colors: + Optional colors for the line strips. + labels: + Optional text labels for the line strips. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "strips": strips, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> LineStrips3D: + """Clear all the fields of a `LineStrips3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + strips=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + class_ids=[], + ) + return inst + + strips: components.LineStrip3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.LineStrip3DBatch._converter, # type: ignore[misc] ) # All the actual 3D line strips that make up the batch. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the line strips. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the line strips. # # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the line strips. # @@ -212,18 +286,18 @@ def _clear(cls) -> LineStrips3D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional [`components.ClassId`][rerun.components.ClassId]s for the lines. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py index c8ef042185e9..5b58a8239e24 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .mesh3d_ext import Mesh3DExt __all__ = ["Mesh3D"] @@ -102,15 +103,15 @@ class Mesh3D(Mesh3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - vertex_positions=None, # type: ignore[arg-type] - triangle_indices=None, # type: ignore[arg-type] - vertex_normals=None, # type: ignore[arg-type] - vertex_colors=None, # type: ignore[arg-type] - vertex_texcoords=None, # type: ignore[arg-type] - albedo_factor=None, # type: ignore[arg-type] - albedo_texture_buffer=None, # type: ignore[arg-type] - albedo_texture_format=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] + vertex_positions=None, + triangle_indices=None, + vertex_normals=None, + vertex_colors=None, + vertex_texcoords=None, + albedo_factor=None, + albedo_texture_buffer=None, + albedo_texture_format=None, + class_ids=None, ) @classmethod @@ -120,9 +121,102 @@ def _clear(cls) -> Mesh3D: inst.__attrs_clear__() return inst - vertex_positions: components.Position3DBatch = field( - metadata={"component": "required"}, - converter=components.Position3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + vertex_positions: datatypes.Vec3DArrayLike | None = None, + triangle_indices: datatypes.UVec3DArrayLike | None = None, + vertex_normals: datatypes.Vec3DArrayLike | None = None, + vertex_colors: datatypes.Rgba32ArrayLike | None = None, + vertex_texcoords: datatypes.Vec2DArrayLike | None = None, + albedo_factor: datatypes.Rgba32Like | None = None, + albedo_texture_buffer: datatypes.BlobLike | None = None, + albedo_texture_format: datatypes.ImageFormatLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + ) -> Mesh3D: + """ + Update only some specific fields of a `Mesh3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + vertex_positions: + The positions of each vertex. + + If no `triangle_indices` are specified, then each triplet of positions is interpreted as a triangle. + triangle_indices: + Optional indices for the triangles that make up the mesh. + vertex_normals: + An optional normal for each vertex. + vertex_colors: + An optional color for each vertex. + vertex_texcoords: + An optional uv texture coordinate for each vertex. + albedo_factor: + A color multiplier applied to the whole mesh. + albedo_texture_buffer: + Optional albedo texture. + + Used with the [`components.Texcoord2D`][rerun.components.Texcoord2D] of the mesh. + + Currently supports only sRGB(A) textures, ignoring alpha. + (meaning that the tensor must have 3 or 4 channels and use the `u8` format) + albedo_texture_format: + The format of the `albedo_texture_buffer`, if any. + class_ids: + Optional class Ids for the vertices. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "vertex_positions": vertex_positions, + "triangle_indices": triangle_indices, + "vertex_normals": vertex_normals, + "vertex_colors": vertex_colors, + "vertex_texcoords": vertex_texcoords, + "albedo_factor": albedo_factor, + "albedo_texture_buffer": albedo_texture_buffer, + "albedo_texture_format": albedo_texture_format, + "class_ids": class_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Mesh3D: + """Clear all the fields of a `Mesh3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + vertex_positions=[], + triangle_indices=[], + vertex_normals=[], + vertex_colors=[], + vertex_texcoords=[], + albedo_factor=[], + albedo_texture_buffer=[], + albedo_texture_format=[], + class_ids=[], + ) + return inst + + vertex_positions: components.Position3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.Position3DBatch._converter, # type: ignore[misc] ) # The positions of each vertex. # @@ -131,54 +225,54 @@ def _clear(cls) -> Mesh3D: # (Docstring intentionally commented out to hide this field from the docs) triangle_indices: components.TriangleIndicesBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TriangleIndicesBatch._optional, # type: ignore[misc] + converter=components.TriangleIndicesBatch._converter, # type: ignore[misc] ) # Optional indices for the triangles that make up the mesh. # # (Docstring intentionally commented out to hide this field from the docs) vertex_normals: components.Vector3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Vector3DBatch._optional, # type: ignore[misc] + converter=components.Vector3DBatch._converter, # type: ignore[misc] ) # An optional normal for each vertex. # # (Docstring intentionally commented out to hide this field from the docs) vertex_colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # An optional color for each vertex. # # (Docstring intentionally commented out to hide this field from the docs) vertex_texcoords: components.Texcoord2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Texcoord2DBatch._optional, # type: ignore[misc] + converter=components.Texcoord2DBatch._converter, # type: ignore[misc] ) # An optional uv texture coordinate for each vertex. # # (Docstring intentionally commented out to hide this field from the docs) albedo_factor: components.AlbedoFactorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AlbedoFactorBatch._optional, # type: ignore[misc] + converter=components.AlbedoFactorBatch._converter, # type: ignore[misc] ) # A color multiplier applied to the whole mesh. # # (Docstring intentionally commented out to hide this field from the docs) albedo_texture_buffer: components.ImageBufferBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ImageBufferBatch._optional, # type: ignore[misc] + converter=components.ImageBufferBatch._converter, # type: ignore[misc] ) # Optional albedo texture. # @@ -190,18 +284,18 @@ def _clear(cls) -> Mesh3D: # (Docstring intentionally commented out to hide this field from the docs) albedo_texture_format: components.ImageFormatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ImageFormatBatch._optional, # type: ignore[misc] + converter=components.ImageFormatBatch._converter, # type: ignore[misc] ) # The format of the `albedo_texture_buffer`, if any. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the vertices. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index b32c37db390a..b175a4173cc4 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .pinhole_ext import PinholeExt __all__ = ["Pinhole"] @@ -75,10 +76,10 @@ class Pinhole(PinholeExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - image_from_camera=None, # type: ignore[arg-type] - resolution=None, # type: ignore[arg-type] - camera_xyz=None, # type: ignore[arg-type] - image_plane_distance=None, # type: ignore[arg-type] + image_from_camera=None, + resolution=None, + camera_xyz=None, + image_plane_distance=None, ) @classmethod @@ -88,18 +89,112 @@ def _clear(cls) -> Pinhole: inst.__attrs_clear__() return inst - image_from_camera: components.PinholeProjectionBatch = field( - metadata={"component": "required"}, - converter=components.PinholeProjectionBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + image_from_camera: datatypes.Mat3x3Like | None = None, + resolution: datatypes.Vec2DLike | None = None, + camera_xyz: datatypes.ViewCoordinatesLike | None = None, + image_plane_distance: datatypes.Float32Like | None = None, + ) -> Pinhole: + """ + Update only some specific fields of a `Pinhole`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + image_from_camera: + Camera projection, from image coordinates to view coordinates. + resolution: + Pixel resolution (usually integers) of child image space. Width and height. + + Example: + ```text + [1920.0, 1440.0] + ``` + + `image_from_camera` project onto the space spanned by `(0,0)` and `resolution - 1`. + camera_xyz: + Sets the view coordinates for the camera. + + All common values are available as constants on the [`components.ViewCoordinates`][rerun.components.ViewCoordinates] class. + + The default is `ViewCoordinates::RDF`, i.e. X=Right, Y=Down, Z=Forward, and this is also the recommended setting. + This means that the camera frustum will point along the positive Z axis of the parent space, + and the cameras "up" direction will be along the negative Y axis of the parent space. + + The camera frustum will point whichever axis is set to `F` (or the opposite of `B`). + When logging a depth image under this entity, this is the direction the point cloud will be projected. + With `RDF`, the default forward is +Z. + + The frustum's "up" direction will be whichever axis is set to `U` (or the opposite of `D`). + This will match the negative Y direction of pixel space (all images are assumed to have xyz=RDF). + With `RDF`, the default is up is -Y. + + The frustum's "right" direction will be whichever axis is set to `R` (or the opposite of `L`). + This will match the positive X direction of pixel space (all images are assumed to have xyz=RDF). + With `RDF`, the default right is +x. + + Other common formats are `RUB` (X=Right, Y=Up, Z=Back) and `FLU` (X=Forward, Y=Left, Z=Up). + + NOTE: setting this to something else than `RDF` (the default) will change the orientation of the camera frustum, + and make the pinhole matrix not match up with the coordinate system of the pinhole entity. + + The pinhole matrix (the `image_from_camera` argument) always project along the third (Z) axis, + but will be re-oriented to project along the forward axis of the `camera_xyz` argument. + image_plane_distance: + The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. + + This is only used for visualization purposes, and does not affect the projection itself. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "image_from_camera": image_from_camera, + "resolution": resolution, + "camera_xyz": camera_xyz, + "image_plane_distance": image_plane_distance, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Pinhole: + """Clear all the fields of a `Pinhole`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + image_from_camera=[], + resolution=[], + camera_xyz=[], + image_plane_distance=[], + ) + return inst + + image_from_camera: components.PinholeProjectionBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.PinholeProjectionBatch._converter, # type: ignore[misc] ) # Camera projection, from image coordinates to view coordinates. # # (Docstring intentionally commented out to hide this field from the docs) resolution: components.ResolutionBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ResolutionBatch._optional, # type: ignore[misc] + converter=components.ResolutionBatch._converter, # type: ignore[misc] ) # Pixel resolution (usually integers) of child image space. Width and height. # @@ -113,9 +208,9 @@ def _clear(cls) -> Pinhole: # (Docstring intentionally commented out to hide this field from the docs) camera_xyz: components.ViewCoordinatesBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ViewCoordinatesBatch._optional, # type: ignore[misc] + converter=components.ViewCoordinatesBatch._converter, # type: ignore[misc] ) # Sets the view coordinates for the camera. # @@ -148,9 +243,9 @@ def _clear(cls) -> Pinhole: # (Docstring intentionally commented out to hide this field from the docs) image_plane_distance: components.ImagePlaneDistanceBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ImagePlaneDistanceBatch._optional, # type: ignore[misc] + converter=components.ImagePlaneDistanceBatch._converter, # type: ignore[misc] ) # The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index 82efdc7e7a7c..2a4c8f88b8d1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .points2d_ext import Points2DExt __all__ = ["Points2D"] @@ -102,14 +103,14 @@ class Points2D(Points2DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - positions=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] - keypoint_ids=None, # type: ignore[arg-type] + positions=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + draw_order=None, + class_ids=None, + keypoint_ids=None, ) @classmethod @@ -119,27 +120,123 @@ def _clear(cls) -> Points2D: inst.__attrs_clear__() return inst - positions: components.Position2DBatch = field( - metadata={"component": "required"}, - converter=components.Position2DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + positions: datatypes.Vec2DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + draw_order: datatypes.Float32Like | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + keypoint_ids: datatypes.KeypointIdArrayLike | None = None, + ) -> Points2D: + """ + Update only some specific fields of a `Points2D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + positions: + All the 2D positions at which the point cloud shows points. + radii: + Optional radii for the points, effectively turning them into circles. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + labels: + Optional text labels for the points. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + keypoint_ids: + Optional keypoint IDs for the points, identifying them within a class. + + If keypoint IDs are passed in but no [`components.ClassId`][rerun.components.ClassId]s were specified, the [`components.ClassId`][rerun.components.ClassId] will + default to 0. + This is useful to identify points within a single classification (which is identified + with `class_id`). + E.g. the classification might be 'Person' and the keypoints refer to joints on a + detected skeleton. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "positions": positions, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "draw_order": draw_order, + "class_ids": class_ids, + "keypoint_ids": keypoint_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Points2D: + """Clear all the fields of a `Points2D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + positions=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + draw_order=[], + class_ids=[], + keypoint_ids=[], + ) + return inst + + positions: components.Position2DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.Position2DBatch._converter, # type: ignore[misc] ) # All the 2D positions at which the point cloud shows points. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the points, effectively turning them into circles. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the points. # @@ -149,9 +246,9 @@ def _clear(cls) -> Points2D: # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the points. # @@ -161,18 +258,18 @@ def _clear(cls) -> Points2D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # @@ -181,9 +278,9 @@ def _clear(cls) -> Points2D: # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the points. # @@ -192,9 +289,9 @@ def _clear(cls) -> Points2D: # (Docstring intentionally commented out to hide this field from the docs) keypoint_ids: components.KeypointIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.KeypointIdBatch._optional, # type: ignore[misc] + converter=components.KeypointIdBatch._converter, # type: ignore[misc] ) # Optional keypoint IDs for the points, identifying them within a class. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index d26e51b6cd61..59e04a50f8c3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .points3d_ext import Points3DExt __all__ = ["Points3D"] @@ -137,13 +138,13 @@ class Points3D(Points3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - positions=None, # type: ignore[arg-type] - radii=None, # type: ignore[arg-type] - colors=None, # type: ignore[arg-type] - labels=None, # type: ignore[arg-type] - show_labels=None, # type: ignore[arg-type] - class_ids=None, # type: ignore[arg-type] - keypoint_ids=None, # type: ignore[arg-type] + positions=None, + radii=None, + colors=None, + labels=None, + show_labels=None, + class_ids=None, + keypoint_ids=None, ) @classmethod @@ -153,27 +154,116 @@ def _clear(cls) -> Points3D: inst.__attrs_clear__() return inst - positions: components.Position3DBatch = field( - metadata={"component": "required"}, - converter=components.Position3DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + positions: datatypes.Vec3DArrayLike | None = None, + radii: datatypes.Float32ArrayLike | None = None, + colors: datatypes.Rgba32ArrayLike | None = None, + labels: datatypes.Utf8ArrayLike | None = None, + show_labels: datatypes.BoolLike | None = None, + class_ids: datatypes.ClassIdArrayLike | None = None, + keypoint_ids: datatypes.KeypointIdArrayLike | None = None, + ) -> Points3D: + """ + Update only some specific fields of a `Points3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + positions: + All the 3D positions at which the point cloud shows points. + radii: + Optional radii for the points, effectively turning them into circles. + colors: + Optional colors for the points. + + The colors are interpreted as RGB or RGBA in sRGB gamma-space, + As either 0-1 floats or 0-255 integers, with separate alpha. + labels: + Optional text labels for the points. + + If there's a single label present, it will be placed at the center of the entity. + Otherwise, each instance will have its own label. + show_labels: + Optional choice of whether the text labels should be shown by default. + class_ids: + Optional class Ids for the points. + + The [`components.ClassId`][rerun.components.ClassId] provides colors and labels if not specified explicitly. + keypoint_ids: + Optional keypoint IDs for the points, identifying them within a class. + + If keypoint IDs are passed in but no [`components.ClassId`][rerun.components.ClassId]s were specified, the [`components.ClassId`][rerun.components.ClassId] will + default to 0. + This is useful to identify points within a single classification (which is identified + with `class_id`). + E.g. the classification might be 'Person' and the keypoints refer to joints on a + detected skeleton. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "positions": positions, + "radii": radii, + "colors": colors, + "labels": labels, + "show_labels": show_labels, + "class_ids": class_ids, + "keypoint_ids": keypoint_ids, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Points3D: + """Clear all the fields of a `Points3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + positions=[], + radii=[], + colors=[], + labels=[], + show_labels=[], + class_ids=[], + keypoint_ids=[], + ) + return inst + + positions: components.Position3DBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.Position3DBatch._converter, # type: ignore[misc] ) # All the 3D positions at which the point cloud shows points. # # (Docstring intentionally commented out to hide this field from the docs) radii: components.RadiusBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] + converter=components.RadiusBatch._converter, # type: ignore[misc] ) # Optional radii for the points, effectively turning them into circles. # # (Docstring intentionally commented out to hide this field from the docs) colors: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional colors for the points. # @@ -183,9 +273,9 @@ def _clear(cls) -> Points3D: # (Docstring intentionally commented out to hide this field from the docs) labels: components.TextBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextBatch._optional, # type: ignore[misc] + converter=components.TextBatch._converter, # type: ignore[misc] ) # Optional text labels for the points. # @@ -195,18 +285,18 @@ def _clear(cls) -> Points3D: # (Docstring intentionally commented out to hide this field from the docs) show_labels: components.ShowLabelsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ShowLabelsBatch._optional, # type: ignore[misc] + converter=components.ShowLabelsBatch._converter, # type: ignore[misc] ) # Optional choice of whether the text labels should be shown by default. # # (Docstring intentionally commented out to hide this field from the docs) class_ids: components.ClassIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ClassIdBatch._optional, # type: ignore[misc] + converter=components.ClassIdBatch._converter, # type: ignore[misc] ) # Optional class Ids for the points. # @@ -215,9 +305,9 @@ def _clear(cls) -> Points3D: # (Docstring intentionally commented out to hide this field from the docs) keypoint_ids: components.KeypointIdBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.KeypointIdBatch._optional, # type: ignore[misc] + converter=components.KeypointIdBatch._converter, # type: ignore[misc] ) # Optional keypoint IDs for the points, identifying them within a class. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 74490b7546da..903a53043511 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -78,7 +78,7 @@ def __init__(self: Any, scalar: datatypes.Float64Like): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - scalar=None, # type: ignore[arg-type] + scalar=None, ) @classmethod @@ -88,9 +88,53 @@ def _clear(cls) -> Scalar: inst.__attrs_clear__() return inst - scalar: components.ScalarBatch = field( - metadata={"component": "required"}, - converter=components.ScalarBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + scalar: datatypes.Float64Like | None = None, + ) -> Scalar: + """ + Update only some specific fields of a `Scalar`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + scalar: + The scalar value to log. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "scalar": scalar, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Scalar: + """Clear all the fields of a `Scalar`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + scalar=[], + ) + return inst + + scalar: components.ScalarBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ScalarBatch._converter, # type: ignore[misc] ) # The scalar value to log. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index 109da3576ec8..31daaff19597 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .segmentation_image_ext import SegmentationImageExt __all__ = ["SegmentationImage"] @@ -64,10 +65,10 @@ class SegmentationImage(SegmentationImageExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - buffer=None, # type: ignore[arg-type] - format=None, # type: ignore[arg-type] - opacity=None, # type: ignore[arg-type] - draw_order=None, # type: ignore[arg-type] + buffer=None, + format=None, + opacity=None, + draw_order=None, ) @classmethod @@ -77,26 +78,90 @@ def _clear(cls) -> SegmentationImage: inst.__attrs_clear__() return inst - buffer: components.ImageBufferBatch = field( - metadata={"component": "required"}, - converter=components.ImageBufferBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + buffer: datatypes.BlobLike | None = None, + format: datatypes.ImageFormatLike | None = None, + opacity: datatypes.Float32Like | None = None, + draw_order: datatypes.Float32Like | None = None, + ) -> SegmentationImage: + """ + Update only some specific fields of a `SegmentationImage`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + buffer: + The raw image data. + format: + The format of the image. + opacity: + Opacity of the image, useful for layering the segmentation image on top of another image. + + Defaults to 0.5 if there's any other images in the scene, otherwise 1.0. + draw_order: + An optional floating point value that specifies the 2D drawing order. + + Objects with higher values are drawn on top of those with lower values. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "buffer": buffer, + "format": format, + "opacity": opacity, + "draw_order": draw_order, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> SegmentationImage: + """Clear all the fields of a `SegmentationImage`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + buffer=[], + format=[], + opacity=[], + draw_order=[], + ) + return inst + + buffer: components.ImageBufferBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageBufferBatch._converter, # type: ignore[misc] ) # The raw image data. # # (Docstring intentionally commented out to hide this field from the docs) - format: components.ImageFormatBatch = field( - metadata={"component": "required"}, - converter=components.ImageFormatBatch._required, # type: ignore[misc] + format: components.ImageFormatBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ImageFormatBatch._converter, # type: ignore[misc] ) # The format of the image. # # (Docstring intentionally commented out to hide this field from the docs) opacity: components.OpacityBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.OpacityBatch._optional, # type: ignore[misc] + converter=components.OpacityBatch._converter, # type: ignore[misc] ) # Opacity of the image, useful for layering the segmentation image on top of another image. # @@ -105,9 +170,9 @@ def _clear(cls) -> SegmentationImage: # (Docstring intentionally commented out to hide this field from the docs) draw_order: components.DrawOrderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.DrawOrderBatch._optional, # type: ignore[misc] + converter=components.DrawOrderBatch._converter, # type: ignore[misc] ) # An optional floating point value that specifies the 2D drawing order. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 8abaed3d5e5b..54b907139ec3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -101,10 +101,10 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - color=None, # type: ignore[arg-type] - width=None, # type: ignore[arg-type] - name=None, # type: ignore[arg-type] - aggregation_policy=None, # type: ignore[arg-type] + color=None, + width=None, + name=None, + aggregation_policy=None, ) @classmethod @@ -114,28 +114,92 @@ def _clear(cls) -> SeriesLine: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + color: datatypes.Rgba32Like | None = None, + width: datatypes.Float32Like | None = None, + name: datatypes.Utf8Like | None = None, + aggregation_policy: components.AggregationPolicyLike | None = None, + ) -> SeriesLine: + """ + Update only some specific fields of a `SeriesLine`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + color: + Color for the corresponding series. + width: + Stroke width for the corresponding series. + name: + Display name of the series. + + Used in the legend. + aggregation_policy: + Configures the zoom-dependent scalar aggregation. + + This is done only if steps on the X axis go below a single pixel, + i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance + (and readability) in such situations as it prevents overdraw. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "color": color, + "width": width, + "name": name, + "aggregation_policy": aggregation_policy, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> SeriesLine: + """Clear all the fields of a `SeriesLine`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + color=[], + width=[], + name=[], + aggregation_policy=[], + ) + return inst + color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Color for the corresponding series. # # (Docstring intentionally commented out to hide this field from the docs) width: components.StrokeWidthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.StrokeWidthBatch._optional, # type: ignore[misc] + converter=components.StrokeWidthBatch._converter, # type: ignore[misc] ) # Stroke width for the corresponding series. # # (Docstring intentionally commented out to hide this field from the docs) name: components.NameBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.NameBatch._optional, # type: ignore[misc] + converter=components.NameBatch._converter, # type: ignore[misc] ) # Display name of the series. # @@ -144,9 +208,9 @@ def _clear(cls) -> SeriesLine: # (Docstring intentionally commented out to hide this field from the docs) aggregation_policy: components.AggregationPolicyBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AggregationPolicyBatch._optional, # type: ignore[misc] + converter=components.AggregationPolicyBatch._converter, # type: ignore[misc] ) # Configures the zoom-dependent scalar aggregation. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index b89d0b51d42f..01347718ffc4 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -115,10 +115,10 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - color=None, # type: ignore[arg-type] - marker=None, # type: ignore[arg-type] - name=None, # type: ignore[arg-type] - marker_size=None, # type: ignore[arg-type] + color=None, + marker=None, + name=None, + marker_size=None, ) @classmethod @@ -128,28 +128,88 @@ def _clear(cls) -> SeriesPoint: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + color: datatypes.Rgba32Like | None = None, + marker: components.MarkerShapeLike | None = None, + name: datatypes.Utf8Like | None = None, + marker_size: datatypes.Float32Like | None = None, + ) -> SeriesPoint: + """ + Update only some specific fields of a `SeriesPoint`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + color: + Color for the corresponding series. + marker: + What shape to use to represent the point + name: + Display name of the series. + + Used in the legend. + marker_size: + Size of the marker. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "color": color, + "marker": marker, + "name": name, + "marker_size": marker_size, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> SeriesPoint: + """Clear all the fields of a `SeriesPoint`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + color=[], + marker=[], + name=[], + marker_size=[], + ) + return inst + color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Color for the corresponding series. # # (Docstring intentionally commented out to hide this field from the docs) marker: components.MarkerShapeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MarkerShapeBatch._optional, # type: ignore[misc] + converter=components.MarkerShapeBatch._converter, # type: ignore[misc] ) # What shape to use to represent the point # # (Docstring intentionally commented out to hide this field from the docs) name: components.NameBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.NameBatch._optional, # type: ignore[misc] + converter=components.NameBatch._converter, # type: ignore[misc] ) # Display name of the series. # @@ -158,9 +218,9 @@ def _clear(cls) -> SeriesPoint: # (Docstring intentionally commented out to hide this field from the docs) marker_size: components.MarkerSizeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MarkerSizeBatch._optional, # type: ignore[misc] + converter=components.MarkerSizeBatch._converter, # type: ignore[misc] ) # Size of the marker. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index 9c9a90ec5cda..b497dcd44544 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .tensor_ext import TensorExt __all__ = ["Tensor"] @@ -56,8 +57,8 @@ class Tensor(TensorExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - data=None, # type: ignore[arg-type] - value_range=None, # type: ignore[arg-type] + data=None, + value_range=None, ) @classmethod @@ -67,18 +68,77 @@ def _clear(cls) -> Tensor: inst.__attrs_clear__() return inst - data: components.TensorDataBatch = field( - metadata={"component": "required"}, - converter=components.TensorDataBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + data: datatypes.TensorDataLike | None = None, + value_range: datatypes.Range1DLike | None = None, + ) -> Tensor: + """ + Update only some specific fields of a `Tensor`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + data: + The tensor data + value_range: + The expected range of values. + + This is typically the expected range of valid values. + Everything outside of the range is clamped to the range for the purpose of colormpaping. + Any colormap applied for display, will map this range. + + If not specified, the range will be automatically estimated from the data. + Note that the Viewer may try to guess a wider range than the minimum/maximum of values + in the contents of the tensor. + E.g. if all values are positive, some bigger than 1.0 and all smaller than 255.0, + the Viewer will guess that the data likely came from an 8bit image, thus assuming a range of 0-255. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "data": data, + "value_range": value_range, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Tensor: + """Clear all the fields of a `Tensor`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + data=[], + value_range=[], + ) + return inst + + data: components.TensorDataBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.TensorDataBatch._converter, # type: ignore[misc] ) # The tensor data # # (Docstring intentionally commented out to hide this field from the docs) value_range: components.ValueRangeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ValueRangeBatch._optional, # type: ignore[misc] + converter=components.ValueRangeBatch._converter, # type: ignore[misc] ) # The expected range of values. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py index 0b0a3b39581f..1c7b001c386b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py @@ -117,8 +117,8 @@ def __init__(self: Any, text: datatypes.Utf8Like, *, media_type: datatypes.Utf8L def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - text=None, # type: ignore[arg-type] - media_type=None, # type: ignore[arg-type] + text=None, + media_type=None, ) @classmethod @@ -128,18 +128,73 @@ def _clear(cls) -> TextDocument: inst.__attrs_clear__() return inst - text: components.TextBatch = field( - metadata={"component": "required"}, - converter=components.TextBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + text: datatypes.Utf8Like | None = None, + media_type: datatypes.Utf8Like | None = None, + ) -> TextDocument: + """ + Update only some specific fields of a `TextDocument`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + text: + Contents of the text document. + media_type: + The Media Type of the text. + + For instance: + * `text/plain` + * `text/markdown` + + If omitted, `text/plain` is assumed. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "text": text, + "media_type": media_type, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> TextDocument: + """Clear all the fields of a `TextDocument`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + text=[], + media_type=[], + ) + return inst + + text: components.TextBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.TextBatch._converter, # type: ignore[misc] ) # Contents of the text document. # # (Docstring intentionally commented out to hide this field from the docs) media_type: components.MediaTypeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MediaTypeBatch._optional, # type: ignore[misc] + converter=components.MediaTypeBatch._converter, # type: ignore[misc] ) # The Media Type of the text. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py index 020c070ea9d6..99dc521f3d52 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py @@ -85,9 +85,9 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - text=None, # type: ignore[arg-type] - level=None, # type: ignore[arg-type] - color=None, # type: ignore[arg-type] + text=None, + level=None, + color=None, ) @classmethod @@ -97,18 +97,74 @@ def _clear(cls) -> TextLog: inst.__attrs_clear__() return inst - text: components.TextBatch = field( - metadata={"component": "required"}, - converter=components.TextBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + text: datatypes.Utf8Like | None = None, + level: datatypes.Utf8Like | None = None, + color: datatypes.Rgba32Like | None = None, + ) -> TextLog: + """ + Update only some specific fields of a `TextLog`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + text: + The body of the message. + level: + The verbosity level of the message. + + This can be used to filter the log messages in the Rerun Viewer. + color: + Optional color to use for the log line in the Rerun Viewer. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "text": text, + "level": level, + "color": color, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> TextLog: + """Clear all the fields of a `TextLog`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + text=[], + level=[], + color=[], + ) + return inst + + text: components.TextBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.TextBatch._converter, # type: ignore[misc] ) # The body of the message. # # (Docstring intentionally commented out to hide this field from the docs) level: components.TextLogLevelBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TextLogLevelBatch._optional, # type: ignore[misc] + converter=components.TextLogLevelBatch._converter, # type: ignore[misc] ) # The verbosity level of the message. # @@ -117,9 +173,9 @@ def _clear(cls) -> TextLog: # (Docstring intentionally commented out to hide this field from the docs) color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Optional color to use for the log line in the Rerun Viewer. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index b2c8e2daa166..caf4ede5d3b2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .transform3d_ext import Transform3DExt __all__ = ["Transform3D"] @@ -140,13 +141,13 @@ class Transform3D(Transform3DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - translation=None, # type: ignore[arg-type] - rotation_axis_angle=None, # type: ignore[arg-type] - quaternion=None, # type: ignore[arg-type] - scale=None, # type: ignore[arg-type] - mat3x3=None, # type: ignore[arg-type] - relation=None, # type: ignore[arg-type] - axis_length=None, # type: ignore[arg-type] + translation=None, + rotation_axis_angle=None, + quaternion=None, + scale=None, + mat3x3=None, + relation=None, + axis_length=None, ) @classmethod @@ -156,64 +157,140 @@ def _clear(cls) -> Transform3D: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + translation: datatypes.Vec3DLike | None = None, + rotation_axis_angle: datatypes.RotationAxisAngleLike | None = None, + quaternion: datatypes.QuaternionLike | None = None, + scale: datatypes.Vec3DLike | None = None, + mat3x3: datatypes.Mat3x3Like | None = None, + relation: components.TransformRelationLike | None = None, + axis_length: datatypes.Float32Like | None = None, + ) -> Transform3D: + """ + Update only some specific fields of a `Transform3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + translation: + Translation vector. + rotation_axis_angle: + Rotation via axis + angle. + quaternion: + Rotation via quaternion. + scale: + Scaling factor. + mat3x3: + 3x3 transformation matrix. + relation: + Specifies the relation this transform establishes between this entity and its parent. + axis_length: + Visual length of the 3 axes. + + The length is interpreted in the local coordinate system of the transform. + If the transform is scaled, the axes will be scaled accordingly. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "translation": translation, + "rotation_axis_angle": rotation_axis_angle, + "quaternion": quaternion, + "scale": scale, + "mat3x3": mat3x3, + "relation": relation, + "axis_length": axis_length, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Transform3D: + """Clear all the fields of a `Transform3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + translation=[], + rotation_axis_angle=[], + quaternion=[], + scale=[], + mat3x3=[], + relation=[], + axis_length=[], + ) + return inst + translation: components.Translation3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Translation3DBatch._required, # type: ignore[misc] + converter=components.Translation3DBatch._converter, # type: ignore[misc] ) # Translation vector. # # (Docstring intentionally commented out to hide this field from the docs) rotation_axis_angle: components.RotationAxisAngleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RotationAxisAngleBatch._required, # type: ignore[misc] + converter=components.RotationAxisAngleBatch._converter, # type: ignore[misc] ) # Rotation via axis + angle. # # (Docstring intentionally commented out to hide this field from the docs) quaternion: components.RotationQuatBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.RotationQuatBatch._required, # type: ignore[misc] + converter=components.RotationQuatBatch._converter, # type: ignore[misc] ) # Rotation via quaternion. # # (Docstring intentionally commented out to hide this field from the docs) scale: components.Scale3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Scale3DBatch._required, # type: ignore[misc] + converter=components.Scale3DBatch._converter, # type: ignore[misc] ) # Scaling factor. # # (Docstring intentionally commented out to hide this field from the docs) mat3x3: components.TransformMat3x3Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TransformMat3x3Batch._required, # type: ignore[misc] + converter=components.TransformMat3x3Batch._converter, # type: ignore[misc] ) # 3x3 transformation matrix. # # (Docstring intentionally commented out to hide this field from the docs) relation: components.TransformRelationBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TransformRelationBatch._required, # type: ignore[misc] + converter=components.TransformRelationBatch._converter, # type: ignore[misc] ) # Specifies the relation this transform establishes between this entity and its parent. # # (Docstring intentionally commented out to hide this field from the docs) axis_length: components.AxisLengthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AxisLengthBatch._required, # type: ignore[misc] + converter=components.AxisLengthBatch._converter, # type: ignore[misc] ) # Visual length of the 3 axes. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py index 7e59ca375224..feddf6276ae2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py @@ -22,6 +22,7 @@ class Transform3DExt: def __init__( self: Any, *, + clear: bool = True, translation: Vec3DLike | None = None, rotation: QuaternionLike | RotationAxisAngleLike | None = None, rotation_axis_angle: RotationAxisAngleLike | None = None, @@ -37,6 +38,8 @@ def __init__( Parameters ---------- + clear: + If true (the default), all unspecified fields will be explicitly cleared. translation: 3D translation vector. rotation: @@ -124,14 +127,25 @@ def __init__( if from_parent: relation = TransformRelation.ChildFromParent - self.__attrs_init__( - translation=translation, - rotation_axis_angle=rotation_axis_angle, - quaternion=quaternion, - scale=scale, - mat3x3=mat3x3, - relation=relation, - axis_length=axis_length, - ) + if clear: + self.__attrs_init__( + translation=translation if translation is not None else [], + rotation_axis_angle=rotation_axis_angle if rotation_axis_angle is not None else [], + quaternion=quaternion if quaternion is not None else [], + scale=scale if scale is not None else [], + mat3x3=mat3x3 if mat3x3 is not None else [], + relation=relation if relation is not None else [], + axis_length=axis_length if axis_length is not None else [], + ) + else: + self.__attrs_init__( + translation=translation, + rotation_axis_angle=rotation_axis_angle, + quaternion=quaternion, + scale=scale, + mat3x3=mat3x3, + relation=relation, + axis_length=axis_length, + ) return self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index dfb627b0ba33..6ecc7ddac2ff 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -7,10 +7,11 @@ from attrs import define, field -from .. import components +from .. import components, datatypes from .._baseclasses import ( Archetype, ) +from ..error_utils import catch_and_log_exceptions from .video_frame_reference_ext import VideoFrameReferenceExt __all__ = ["VideoFrameReference"] @@ -115,8 +116,8 @@ class VideoFrameReference(VideoFrameReferenceExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - timestamp=None, # type: ignore[arg-type] - video_reference=None, # type: ignore[arg-type] + timestamp=None, + video_reference=None, ) @classmethod @@ -126,9 +127,73 @@ def _clear(cls) -> VideoFrameReference: inst.__attrs_clear__() return inst - timestamp: components.VideoTimestampBatch = field( - metadata={"component": "required"}, - converter=components.VideoTimestampBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + timestamp: datatypes.VideoTimestampLike | None = None, + video_reference: datatypes.EntityPathLike | None = None, + ) -> VideoFrameReference: + """ + Update only some specific fields of a `VideoFrameReference`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + timestamp: + References the closest video frame to this timestamp. + + Note that this uses the closest video frame instead of the latest at this timestamp + in order to be more forgiving of rounding errors for inprecise timestamp types. + + Timestamps are relative to the start of the video, i.e. a timestamp of 0 always corresponds to the first frame. + This is oftentimes equivalent to presentation timestamps (known as PTS), but in the presence of B-frames + (bidirectionally predicted frames) there may be an offset on the first presentation timestamp in the video. + video_reference: + Optional reference to an entity with a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo]. + + If none is specified, the video is assumed to be at the same entity. + Note that blueprint overrides on the referenced video will be ignored regardless, + as this is always interpreted as a reference to the data store. + + For a series of video frame references, it is recommended to specify this path only once + at the beginning of the series and then rely on latest-at query semantics to + keep the video reference active. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "timestamp": timestamp, + "video_reference": video_reference, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> VideoFrameReference: + """Clear all the fields of a `VideoFrameReference`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + timestamp=[], + video_reference=[], + ) + return inst + + timestamp: components.VideoTimestampBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.VideoTimestampBatch._converter, # type: ignore[misc] ) # References the closest video frame to this timestamp. # @@ -142,9 +207,9 @@ def _clear(cls) -> VideoFrameReference: # (Docstring intentionally commented out to hide this field from the docs) video_reference: components.EntityPathBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.EntityPathBatch._optional, # type: ignore[misc] + converter=components.EntityPathBatch._converter, # type: ignore[misc] ) # Optional reference to an entity with a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo]. # diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index ada329cf25a9..413bc403160d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -84,7 +84,7 @@ def __init__(self: Any, xyz: datatypes.ViewCoordinatesLike): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - xyz=None, # type: ignore[arg-type] + xyz=None, ) @classmethod @@ -94,9 +94,53 @@ def _clear(cls) -> ViewCoordinates: inst.__attrs_clear__() return inst - xyz: components.ViewCoordinatesBatch = field( - metadata={"component": "required"}, - converter=components.ViewCoordinatesBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + xyz: datatypes.ViewCoordinatesLike | None = None, + ) -> ViewCoordinates: + """ + Update only some specific fields of a `ViewCoordinates`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + xyz: + The directions of the [x, y, z] axes. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "xyz": xyz, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ViewCoordinates: + """Clear all the fields of a `ViewCoordinates`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + xyz=[], + ) + return inst + + xyz: components.ViewCoordinatesBatch | None = field( + metadata={"component": True}, + default=None, + converter=components.ViewCoordinatesBatch._converter, # type: ignore[misc] ) # The directions of the [x, y, z] axes. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py index cbe9178d7911..f2595b02b7e1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py @@ -7,11 +7,12 @@ from attrs import define, field -from ... import components +from ... import components, datatypes from ..._baseclasses import ( Archetype, ) from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions from .background_ext import BackgroundExt __all__ = ["Background"] @@ -26,8 +27,8 @@ class Background(BackgroundExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - kind=None, # type: ignore[arg-type] - color=None, # type: ignore[arg-type] + kind=None, + color=None, ) @classmethod @@ -37,18 +38,67 @@ def _clear(cls) -> Background: inst.__attrs_clear__() return inst - kind: blueprint_components.BackgroundKindBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.BackgroundKindBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + kind: blueprint_components.BackgroundKindLike | None = None, + color: datatypes.Rgba32Like | None = None, + ) -> Background: + """ + Update only some specific fields of a `Background`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + kind: + The type of the background. + color: + Color used for the solid background type. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "kind": kind, + "color": color, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> Background: + """Clear all the fields of a `Background`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + kind=[], + color=[], + ) + return inst + + kind: blueprint_components.BackgroundKindBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.BackgroundKindBatch._converter, # type: ignore[misc] ) # The type of the background. # # (Docstring intentionally commented out to hide this field from the docs) color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Color used for the solid background type. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py index 9f225bd61254..e5970123ebae 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/container_blueprint.py @@ -93,14 +93,14 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - container_kind=None, # type: ignore[arg-type] - display_name=None, # type: ignore[arg-type] - contents=None, # type: ignore[arg-type] - col_shares=None, # type: ignore[arg-type] - row_shares=None, # type: ignore[arg-type] - active_tab=None, # type: ignore[arg-type] - visible=None, # type: ignore[arg-type] - grid_columns=None, # type: ignore[arg-type] + container_kind=None, + display_name=None, + contents=None, + col_shares=None, + row_shares=None, + active_tab=None, + visible=None, + grid_columns=None, ) @classmethod @@ -110,36 +110,131 @@ def _clear(cls) -> ContainerBlueprint: inst.__attrs_clear__() return inst - container_kind: blueprint_components.ContainerKindBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.ContainerKindBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + container_kind: blueprint_components.ContainerKindLike | None = None, + display_name: datatypes.Utf8Like | None = None, + contents: datatypes.EntityPathArrayLike | None = None, + col_shares: datatypes.Float32ArrayLike | None = None, + row_shares: datatypes.Float32ArrayLike | None = None, + active_tab: datatypes.EntityPathLike | None = None, + visible: datatypes.BoolLike | None = None, + grid_columns: datatypes.UInt32Like | None = None, + ) -> ContainerBlueprint: + """ + Update only some specific fields of a `ContainerBlueprint`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + container_kind: + The class of the view. + display_name: + The name of the container. + contents: + `ContainerId`s or `ViewId`s that are children of this container. + col_shares: + The layout shares of each column in the container. + + For [`components.ContainerKind.Horizontal`][rerun.blueprint.components.ContainerKind.Horizontal] containers, the length of this list should always match the number of contents. + + Ignored for [`components.ContainerKind.Vertical`][rerun.blueprint.components.ContainerKind.Vertical] containers. + row_shares: + The layout shares of each row of the container. + + For [`components.ContainerKind.Vertical`][rerun.blueprint.components.ContainerKind.Vertical] containers, the length of this list should always match the number of contents. + + Ignored for [`components.ContainerKind.Horizontal`][rerun.blueprint.components.ContainerKind.Horizontal] containers. + active_tab: + Which tab is active. + + Only applies to `Tabs` containers. + visible: + Whether this container is visible. + + Defaults to true if not specified. + grid_columns: + How many columns this grid should have. + + If unset, the grid layout will be auto. + + Ignored for [`components.ContainerKind.Horizontal`][rerun.blueprint.components.ContainerKind.Horizontal]/[`components.ContainerKind.Vertical`][rerun.blueprint.components.ContainerKind.Vertical] containers. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "container_kind": container_kind, + "display_name": display_name, + "contents": contents, + "col_shares": col_shares, + "row_shares": row_shares, + "active_tab": active_tab, + "visible": visible, + "grid_columns": grid_columns, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ContainerBlueprint: + """Clear all the fields of a `ContainerBlueprint`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + container_kind=[], + display_name=[], + contents=[], + col_shares=[], + row_shares=[], + active_tab=[], + visible=[], + grid_columns=[], + ) + return inst + + container_kind: blueprint_components.ContainerKindBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.ContainerKindBatch._converter, # type: ignore[misc] ) # The class of the view. # # (Docstring intentionally commented out to hide this field from the docs) display_name: components.NameBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.NameBatch._optional, # type: ignore[misc] + converter=components.NameBatch._converter, # type: ignore[misc] ) # The name of the container. # # (Docstring intentionally commented out to hide this field from the docs) contents: blueprint_components.IncludedContentBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.IncludedContentBatch._optional, # type: ignore[misc] + converter=blueprint_components.IncludedContentBatch._converter, # type: ignore[misc] ) # `ContainerId`s or `ViewId`s that are children of this container. # # (Docstring intentionally commented out to hide this field from the docs) col_shares: blueprint_components.ColumnShareBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ColumnShareBatch._optional, # type: ignore[misc] + converter=blueprint_components.ColumnShareBatch._converter, # type: ignore[misc] ) # The layout shares of each column in the container. # @@ -150,9 +245,9 @@ def _clear(cls) -> ContainerBlueprint: # (Docstring intentionally commented out to hide this field from the docs) row_shares: blueprint_components.RowShareBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.RowShareBatch._optional, # type: ignore[misc] + converter=blueprint_components.RowShareBatch._converter, # type: ignore[misc] ) # The layout shares of each row of the container. # @@ -163,9 +258,9 @@ def _clear(cls) -> ContainerBlueprint: # (Docstring intentionally commented out to hide this field from the docs) active_tab: blueprint_components.ActiveTabBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ActiveTabBatch._optional, # type: ignore[misc] + converter=blueprint_components.ActiveTabBatch._converter, # type: ignore[misc] ) # Which tab is active. # @@ -174,9 +269,9 @@ def _clear(cls) -> ContainerBlueprint: # (Docstring intentionally commented out to hide this field from the docs) visible: blueprint_components.VisibleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.VisibleBatch._optional, # type: ignore[misc] + converter=blueprint_components.VisibleBatch._converter, # type: ignore[misc] ) # Whether this container is visible. # @@ -185,9 +280,9 @@ def _clear(cls) -> ContainerBlueprint: # (Docstring intentionally commented out to hide this field from the docs) grid_columns: blueprint_components.GridColumnsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.GridColumnsBatch._optional, # type: ignore[misc] + converter=blueprint_components.GridColumnsBatch._converter, # type: ignore[misc] ) # How many columns this grid should have. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py index 3bc64d3dda93..5e41b02d27af 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/dataframe_query.py @@ -7,10 +7,12 @@ from attrs import define, field +from ... import datatypes from ..._baseclasses import ( Archetype, ) -from ...blueprint import components as blueprint_components +from ...blueprint import components as blueprint_components, datatypes as blueprint_datatypes +from ...error_utils import catch_and_log_exceptions from .dataframe_query_ext import DataframeQueryExt __all__ = ["DataframeQuery"] @@ -25,11 +27,11 @@ class DataframeQuery(DataframeQueryExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - timeline=None, # type: ignore[arg-type] - filter_by_range=None, # type: ignore[arg-type] - filter_is_not_null=None, # type: ignore[arg-type] - apply_latest_at=None, # type: ignore[arg-type] - select=None, # type: ignore[arg-type] + timeline=None, + filter_by_range=None, + filter_is_not_null=None, + apply_latest_at=None, + select=None, ) @classmethod @@ -39,10 +41,77 @@ def _clear(cls) -> DataframeQuery: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + timeline: datatypes.Utf8Like | None = None, + filter_by_range: blueprint_datatypes.FilterByRangeLike | None = None, + filter_is_not_null: blueprint_datatypes.FilterIsNotNullLike | None = None, + apply_latest_at: datatypes.BoolLike | None = None, + select: blueprint_datatypes.SelectedColumnsLike | None = None, + ) -> DataframeQuery: + """ + Update only some specific fields of a `DataframeQuery`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + timeline: + The timeline for this query. + + If unset, the timeline currently active on the time panel is used. + filter_by_range: + If provided, only rows whose timestamp is within this range will be shown. + + Note: will be unset as soon as `timeline` is changed. + filter_is_not_null: + If provided, only show rows which contains a logged event for the specified component. + apply_latest_at: + Should empty cells be filled with latest-at queries? + select: + Selected columns. If unset, all columns are selected. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "timeline": timeline, + "filter_by_range": filter_by_range, + "filter_is_not_null": filter_is_not_null, + "apply_latest_at": apply_latest_at, + "select": select, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> DataframeQuery: + """Clear all the fields of a `DataframeQuery`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + timeline=[], + filter_by_range=[], + filter_is_not_null=[], + apply_latest_at=[], + select=[], + ) + return inst + timeline: blueprint_components.TimelineNameBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.TimelineNameBatch._optional, # type: ignore[misc] + converter=blueprint_components.TimelineNameBatch._converter, # type: ignore[misc] ) # The timeline for this query. # @@ -51,9 +120,9 @@ def _clear(cls) -> DataframeQuery: # (Docstring intentionally commented out to hide this field from the docs) filter_by_range: blueprint_components.FilterByRangeBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.FilterByRangeBatch._optional, # type: ignore[misc] + converter=blueprint_components.FilterByRangeBatch._converter, # type: ignore[misc] ) # If provided, only rows whose timestamp is within this range will be shown. # @@ -62,27 +131,27 @@ def _clear(cls) -> DataframeQuery: # (Docstring intentionally commented out to hide this field from the docs) filter_is_not_null: blueprint_components.FilterIsNotNullBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.FilterIsNotNullBatch._optional, # type: ignore[misc] + converter=blueprint_components.FilterIsNotNullBatch._converter, # type: ignore[misc] ) # If provided, only show rows which contains a logged event for the specified component. # # (Docstring intentionally commented out to hide this field from the docs) apply_latest_at: blueprint_components.ApplyLatestAtBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ApplyLatestAtBatch._optional, # type: ignore[misc] + converter=blueprint_components.ApplyLatestAtBatch._converter, # type: ignore[misc] ) # Should empty cells be filled with latest-at queries? # # (Docstring intentionally commented out to hide this field from the docs) select: blueprint_components.SelectedColumnsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.SelectedColumnsBatch._optional, # type: ignore[misc] + converter=blueprint_components.SelectedColumnsBatch._converter, # type: ignore[misc] ) # Selected columns. If unset, all columns are selected. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py index 5804b3c0db7f..f708724dbaa1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py @@ -49,8 +49,8 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - enabled=None, # type: ignore[arg-type] - strength=None, # type: ignore[arg-type] + enabled=None, + strength=None, ) @classmethod @@ -60,10 +60,60 @@ def _clear(cls) -> ForceCenter: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + ) -> ForceCenter: + """ + Update only some specific fields of a `ForceCenter`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + enabled: + Whether the center force is enabled. + + The center force tries to move the center of mass of the graph towards the origin. + strength: + The strength of the force. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "enabled": enabled, + "strength": strength, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ForceCenter: + """Clear all the fields of a `ForceCenter`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + enabled=[], + strength=[], + ) + return inst + enabled: blueprint_components.EnabledBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + converter=blueprint_components.EnabledBatch._converter, # type: ignore[misc] ) # Whether the center force is enabled. # @@ -72,9 +122,9 @@ def _clear(cls) -> ForceCenter: # (Docstring intentionally commented out to hide this field from the docs) strength: blueprint_components.ForceStrengthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceStrengthBatch._converter, # type: ignore[misc] ) # The strength of the force. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py index 169c8f5e7ba0..5c2e3f83d7e2 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py @@ -57,9 +57,9 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - enabled=None, # type: ignore[arg-type] - strength=None, # type: ignore[arg-type] - iterations=None, # type: ignore[arg-type] + enabled=None, + strength=None, + iterations=None, ) @classmethod @@ -69,10 +69,67 @@ def _clear(cls) -> ForceCollisionRadius: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + iterations: datatypes.UInt64Like | None = None, + ) -> ForceCollisionRadius: + """ + Update only some specific fields of a `ForceCollisionRadius`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + enabled: + Whether the collision force is enabled. + + The collision force resolves collisions between nodes based on the bounding circle defined by their radius. + strength: + The strength of the force. + iterations: + Specifies how often this force should be applied per iteration. + + Increasing this parameter can lead to better results at the cost of longer computation time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "enabled": enabled, + "strength": strength, + "iterations": iterations, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ForceCollisionRadius: + """Clear all the fields of a `ForceCollisionRadius`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + enabled=[], + strength=[], + iterations=[], + ) + return inst + enabled: blueprint_components.EnabledBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + converter=blueprint_components.EnabledBatch._converter, # type: ignore[misc] ) # Whether the collision force is enabled. # @@ -81,18 +138,18 @@ def _clear(cls) -> ForceCollisionRadius: # (Docstring intentionally commented out to hide this field from the docs) strength: blueprint_components.ForceStrengthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceStrengthBatch._converter, # type: ignore[misc] ) # The strength of the force. # # (Docstring intentionally commented out to hide this field from the docs) iterations: blueprint_components.ForceIterationsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceIterationsBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceIterationsBatch._converter, # type: ignore[misc] ) # Specifies how often this force should be applied per iteration. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py index f3c179715a0a..f93e9c6fcf46 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py @@ -57,9 +57,9 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - enabled=None, # type: ignore[arg-type] - distance=None, # type: ignore[arg-type] - iterations=None, # type: ignore[arg-type] + enabled=None, + distance=None, + iterations=None, ) @classmethod @@ -69,10 +69,67 @@ def _clear(cls) -> ForceLink: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + enabled: datatypes.BoolLike | None = None, + distance: datatypes.Float64Like | None = None, + iterations: datatypes.UInt64Like | None = None, + ) -> ForceLink: + """ + Update only some specific fields of a `ForceLink`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + enabled: + Whether the link force is enabled. + + The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. + distance: + The target distance between two nodes. + iterations: + Specifies how often this force should be applied per iteration. + + Increasing this parameter can lead to better results at the cost of longer computation time. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "enabled": enabled, + "distance": distance, + "iterations": iterations, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ForceLink: + """Clear all the fields of a `ForceLink`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + enabled=[], + distance=[], + iterations=[], + ) + return inst + enabled: blueprint_components.EnabledBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + converter=blueprint_components.EnabledBatch._converter, # type: ignore[misc] ) # Whether the link force is enabled. # @@ -81,18 +138,18 @@ def _clear(cls) -> ForceLink: # (Docstring intentionally commented out to hide this field from the docs) distance: blueprint_components.ForceDistanceBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceDistanceBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceDistanceBatch._converter, # type: ignore[misc] ) # The target distance between two nodes. # # (Docstring intentionally commented out to hide this field from the docs) iterations: blueprint_components.ForceIterationsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceIterationsBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceIterationsBatch._converter, # type: ignore[misc] ) # Specifies how often this force should be applied per iteration. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py index 1881af385409..34592296ee55 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py @@ -56,8 +56,8 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - enabled=None, # type: ignore[arg-type] - strength=None, # type: ignore[arg-type] + enabled=None, + strength=None, ) @classmethod @@ -67,10 +67,63 @@ def _clear(cls) -> ForceManyBody: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + ) -> ForceManyBody: + """ + Update only some specific fields of a `ForceManyBody`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + enabled: + Whether the many body force is enabled. + + The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. + strength: + The strength of the force. + + If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "enabled": enabled, + "strength": strength, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ForceManyBody: + """Clear all the fields of a `ForceManyBody`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + enabled=[], + strength=[], + ) + return inst + enabled: blueprint_components.EnabledBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + converter=blueprint_components.EnabledBatch._converter, # type: ignore[misc] ) # Whether the many body force is enabled. # @@ -80,9 +133,9 @@ def _clear(cls) -> ForceManyBody: # (Docstring intentionally commented out to hide this field from the docs) strength: blueprint_components.ForceStrengthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceStrengthBatch._converter, # type: ignore[misc] ) # The strength of the force. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py index aa83eb92516d..e717533ffafe 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py @@ -55,9 +55,9 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - enabled=None, # type: ignore[arg-type] - strength=None, # type: ignore[arg-type] - position=None, # type: ignore[arg-type] + enabled=None, + strength=None, + position=None, ) @classmethod @@ -67,10 +67,65 @@ def _clear(cls) -> ForcePosition: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + enabled: datatypes.BoolLike | None = None, + strength: datatypes.Float64Like | None = None, + position: datatypes.Vec2DLike | None = None, + ) -> ForcePosition: + """ + Update only some specific fields of a `ForcePosition`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + enabled: + Whether the position force is enabled. + + The position force pulls nodes towards a specific position, similar to gravity. + strength: + The strength of the force. + position: + The position where the nodes should be pulled towards. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "enabled": enabled, + "strength": strength, + "position": position, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ForcePosition: + """Clear all the fields of a `ForcePosition`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + enabled=[], + strength=[], + position=[], + ) + return inst + enabled: blueprint_components.EnabledBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] + converter=blueprint_components.EnabledBatch._converter, # type: ignore[misc] ) # Whether the position force is enabled. # @@ -79,18 +134,18 @@ def _clear(cls) -> ForcePosition: # (Docstring intentionally commented out to hide this field from the docs) strength: blueprint_components.ForceStrengthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ForceStrengthBatch._optional, # type: ignore[misc] + converter=blueprint_components.ForceStrengthBatch._converter, # type: ignore[misc] ) # The strength of the force. # # (Docstring intentionally commented out to hide this field from the docs) position: components.Position2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Position2DBatch._optional, # type: ignore[misc] + converter=components.Position2DBatch._converter, # type: ignore[misc] ) # The position where the nodes should be pulled towards. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py index a34c8f217b9c..185931a38ed3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/line_grid3d.py @@ -71,11 +71,11 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - visible=None, # type: ignore[arg-type] - spacing=None, # type: ignore[arg-type] - plane=None, # type: ignore[arg-type] - stroke_width=None, # type: ignore[arg-type] - color=None, # type: ignore[arg-type] + visible=None, + spacing=None, + plane=None, + stroke_width=None, + color=None, ) @classmethod @@ -85,10 +85,85 @@ def _clear(cls) -> LineGrid3D: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + visible: datatypes.BoolLike | None = None, + spacing: datatypes.Float32Like | None = None, + plane: datatypes.Plane3DLike | None = None, + stroke_width: datatypes.Float32Like | None = None, + color: datatypes.Rgba32Like | None = None, + ) -> LineGrid3D: + """ + Update only some specific fields of a `LineGrid3D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + visible: + Whether the grid is visible. + + Defaults to true. + spacing: + Space between grid lines spacing of one line to the next in scene units. + + As you zoom out, successively only every tenth line is shown. + This controls the closest zoom level. + plane: + In what plane the grid is drawn. + + Defaults to whatever plane is determined as the plane at zero units up/down as defined by [`components.ViewCoordinates`][rerun.components.ViewCoordinates] if present. + stroke_width: + How thick the lines should be in ui units. + + Default is 1.0 ui unit. + color: + Color used for the grid. + + Transparency via alpha channel is supported. + Defaults to a slightly transparent light gray. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "visible": visible, + "spacing": spacing, + "plane": plane, + "stroke_width": stroke_width, + "color": color, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> LineGrid3D: + """Clear all the fields of a `LineGrid3D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + visible=[], + spacing=[], + plane=[], + stroke_width=[], + color=[], + ) + return inst + visible: blueprint_components.VisibleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.VisibleBatch._optional, # type: ignore[misc] + converter=blueprint_components.VisibleBatch._converter, # type: ignore[misc] ) # Whether the grid is visible. # @@ -97,9 +172,9 @@ def _clear(cls) -> LineGrid3D: # (Docstring intentionally commented out to hide this field from the docs) spacing: blueprint_components.GridSpacingBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.GridSpacingBatch._optional, # type: ignore[misc] + converter=blueprint_components.GridSpacingBatch._converter, # type: ignore[misc] ) # Space between grid lines spacing of one line to the next in scene units. # @@ -109,9 +184,9 @@ def _clear(cls) -> LineGrid3D: # (Docstring intentionally commented out to hide this field from the docs) plane: components.Plane3DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Plane3DBatch._optional, # type: ignore[misc] + converter=components.Plane3DBatch._converter, # type: ignore[misc] ) # In what plane the grid is drawn. # @@ -120,9 +195,9 @@ def _clear(cls) -> LineGrid3D: # (Docstring intentionally commented out to hide this field from the docs) stroke_width: components.StrokeWidthBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.StrokeWidthBatch._optional, # type: ignore[misc] + converter=components.StrokeWidthBatch._converter, # type: ignore[misc] ) # How thick the lines should be in ui units. # @@ -131,9 +206,9 @@ def _clear(cls) -> LineGrid3D: # (Docstring intentionally commented out to hide this field from the docs) color: components.ColorBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] + converter=components.ColorBatch._converter, # type: ignore[misc] ) # Color used for the grid. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py index bd32323fc481..a769a61eccce 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_background.py @@ -44,7 +44,7 @@ def __init__(self: Any, provider: blueprint_components.MapProviderLike): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - provider=None, # type: ignore[arg-type] + provider=None, ) @classmethod @@ -54,9 +54,55 @@ def _clear(cls) -> MapBackground: inst.__attrs_clear__() return inst - provider: blueprint_components.MapProviderBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.MapProviderBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + provider: blueprint_components.MapProviderLike | None = None, + ) -> MapBackground: + """ + Update only some specific fields of a `MapBackground`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + provider: + Map provider and style to use. + + **Note**: Requires a Mapbox API key in the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "provider": provider, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> MapBackground: + """Clear all the fields of a `MapBackground`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + provider=[], + ) + return inst + + provider: blueprint_components.MapProviderBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.MapProviderBatch._converter, # type: ignore[misc] ) # Map provider and style to use. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py index 95bb17027799..c299108f602f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/map_zoom.py @@ -45,7 +45,7 @@ def __init__(self: Any, zoom: datatypes.Float64Like): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - zoom=None, # type: ignore[arg-type] + zoom=None, ) @classmethod @@ -55,9 +55,55 @@ def _clear(cls) -> MapZoom: inst.__attrs_clear__() return inst - zoom: blueprint_components.ZoomLevelBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.ZoomLevelBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + zoom: datatypes.Float64Like | None = None, + ) -> MapZoom: + """ + Update only some specific fields of a `MapZoom`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + zoom: + Zoom level for the map. + + Zoom level follow the [`OpenStreetMap` definition](https://wiki.openstreetmap.org/wiki/Zoom_levels). + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "zoom": zoom, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> MapZoom: + """Clear all the fields of a `MapZoom`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + zoom=[], + ) + return inst + + zoom: blueprint_components.ZoomLevelBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.ZoomLevelBatch._converter, # type: ignore[misc] ) # Zoom level for the map. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py index dee3bdaccadb..dd4bf470bc5e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/near_clip_plane.py @@ -45,7 +45,7 @@ def __init__(self: Any, near_clip_plane: datatypes.Float32Like): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - near_clip_plane=None, # type: ignore[arg-type] + near_clip_plane=None, ) @classmethod @@ -55,9 +55,55 @@ def _clear(cls) -> NearClipPlane: inst.__attrs_clear__() return inst - near_clip_plane: blueprint_components.NearClipPlaneBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.NearClipPlaneBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + near_clip_plane: datatypes.Float32Like | None = None, + ) -> NearClipPlane: + """ + Update only some specific fields of a `NearClipPlane`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + near_clip_plane: + Controls the distance to the near clip plane in 3D scene units. + + Content closer than this distance will not be visible. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "near_clip_plane": near_clip_plane, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> NearClipPlane: + """Clear all the fields of a `NearClipPlane`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + near_clip_plane=[], + ) + return inst + + near_clip_plane: blueprint_components.NearClipPlaneBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.NearClipPlaneBatch._converter, # type: ignore[misc] ) # Controls the distance to the near clip plane in 3D scene units. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py index e9554a2d2053..12ac91c7680b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py @@ -42,7 +42,7 @@ def __init__(self: Any, *, state: blueprint_components.PanelStateLike | None = N def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - state=None, # type: ignore[arg-type] + state=None, ) @classmethod @@ -52,10 +52,53 @@ def _clear(cls) -> PanelBlueprint: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + state: blueprint_components.PanelStateLike | None = None, + ) -> PanelBlueprint: + """ + Update only some specific fields of a `PanelBlueprint`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + state: + Current state of the panels. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "state": state, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> PanelBlueprint: + """Clear all the fields of a `PanelBlueprint`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + state=[], + ) + return inst + state: blueprint_components.PanelStateBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.PanelStateBatch._optional, # type: ignore[misc] + converter=blueprint_components.PanelStateBatch._converter, # type: ignore[misc] ) # Current state of the panels. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py index 22a64b7aeb1f..c035b1ba751a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py @@ -7,10 +7,12 @@ from attrs import define, field +from ... import datatypes from ..._baseclasses import ( Archetype, ) from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions from .plot_legend_ext import PlotLegendExt __all__ = ["PlotLegend"] @@ -25,8 +27,8 @@ class PlotLegend(PlotLegendExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - corner=None, # type: ignore[arg-type] - visible=None, # type: ignore[arg-type] + corner=None, + visible=None, ) @classmethod @@ -36,10 +38,62 @@ def _clear(cls) -> PlotLegend: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + corner: blueprint_components.Corner2DLike | None = None, + visible: datatypes.BoolLike | None = None, + ) -> PlotLegend: + """ + Update only some specific fields of a `PlotLegend`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + corner: + To what corner the legend is aligned. + + Defaults to the right bottom corner. + visible: + Whether the legend is shown at all. + + True by default. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "corner": corner, + "visible": visible, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> PlotLegend: + """Clear all the fields of a `PlotLegend`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + corner=[], + visible=[], + ) + return inst + corner: blueprint_components.Corner2DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.Corner2DBatch._optional, # type: ignore[misc] + converter=blueprint_components.Corner2DBatch._converter, # type: ignore[misc] ) # To what corner the legend is aligned. # @@ -48,9 +102,9 @@ def _clear(cls) -> PlotLegend: # (Docstring intentionally commented out to hide this field from the docs) visible: blueprint_components.VisibleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.VisibleBatch._optional, # type: ignore[misc] + converter=blueprint_components.VisibleBatch._converter, # type: ignore[misc] ) # Whether the legend is shown at all. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py index 3228f024591b..72ebe55abf4d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py @@ -47,8 +47,8 @@ def __init__(self: Any, *, range: datatypes.Range1DLike | None = None, zoom_lock def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - range=None, # type: ignore[arg-type] - zoom_lock=None, # type: ignore[arg-type] + range=None, + zoom_lock=None, ) @classmethod @@ -58,10 +58,60 @@ def _clear(cls) -> ScalarAxis: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + range: datatypes.Range1DLike | None = None, + zoom_lock: datatypes.BoolLike | None = None, + ) -> ScalarAxis: + """ + Update only some specific fields of a `ScalarAxis`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + range: + The range of the axis. + + If unset, the range well be automatically determined based on the queried data. + zoom_lock: + If enabled, the Y axis range will remain locked to the specified range when zooming. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "range": range, + "zoom_lock": zoom_lock, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ScalarAxis: + """Clear all the fields of a `ScalarAxis`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + range=[], + zoom_lock=[], + ) + return inst + range: components.Range1DBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.Range1DBatch._optional, # type: ignore[misc] + converter=components.Range1DBatch._converter, # type: ignore[misc] ) # The range of the axis. # @@ -70,9 +120,9 @@ def _clear(cls) -> ScalarAxis: # (Docstring intentionally commented out to hide this field from the docs) zoom_lock: blueprint_components.LockRangeDuringZoomBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.LockRangeDuringZoomBatch._optional, # type: ignore[misc] + converter=blueprint_components.LockRangeDuringZoomBatch._converter, # type: ignore[misc] ) # If enabled, the Y axis range will remain locked to the specified range when zooming. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py index f0a1157f5462..3ac46c4cd514 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_scalar_mapping.py @@ -60,9 +60,9 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - mag_filter=None, # type: ignore[arg-type] - colormap=None, # type: ignore[arg-type] - gamma=None, # type: ignore[arg-type] + mag_filter=None, + colormap=None, + gamma=None, ) @classmethod @@ -72,10 +72,71 @@ def _clear(cls) -> TensorScalarMapping: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + mag_filter: components.MagnificationFilterLike | None = None, + colormap: components.ColormapLike | None = None, + gamma: datatypes.Float32Like | None = None, + ) -> TensorScalarMapping: + """ + Update only some specific fields of a `TensorScalarMapping`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + mag_filter: + Filter used when zooming in on the tensor. + + Note that the filter is applied to the scalar values *before* they are mapped to color. + colormap: + How scalar values map to colors. + gamma: + Gamma exponent applied to normalized values before mapping to color. + + Raises the normalized values to the power of this value before mapping to color. + Acts like an inverse brightness. Defaults to 1.0. + + The final value for display is set as: + `colormap( ((value - data_display_range.min) / (data_display_range.max - data_display_range.min)) ** gamma )` + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "mag_filter": mag_filter, + "colormap": colormap, + "gamma": gamma, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> TensorScalarMapping: + """Clear all the fields of a `TensorScalarMapping`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + mag_filter=[], + colormap=[], + gamma=[], + ) + return inst + mag_filter: components.MagnificationFilterBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.MagnificationFilterBatch._optional, # type: ignore[misc] + converter=components.MagnificationFilterBatch._converter, # type: ignore[misc] ) # Filter used when zooming in on the tensor. # @@ -84,18 +145,18 @@ def _clear(cls) -> TensorScalarMapping: # (Docstring intentionally commented out to hide this field from the docs) colormap: components.ColormapBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.ColormapBatch._optional, # type: ignore[misc] + converter=components.ColormapBatch._converter, # type: ignore[misc] ) # How scalar values map to colors. # # (Docstring intentionally commented out to hide this field from the docs) gamma: components.GammaCorrectionBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.GammaCorrectionBatch._optional, # type: ignore[misc] + converter=components.GammaCorrectionBatch._converter, # type: ignore[misc] ) # Gamma exponent applied to normalized values before mapping to color. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py index 419acbb84323..8f940ff38a27 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_slice_selection.py @@ -66,10 +66,10 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - width=None, # type: ignore[arg-type] - height=None, # type: ignore[arg-type] - indices=None, # type: ignore[arg-type] - slider=None, # type: ignore[arg-type] + width=None, + height=None, + indices=None, + slider=None, ) @classmethod @@ -79,10 +79,78 @@ def _clear(cls) -> TensorSliceSelection: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + width: datatypes.TensorDimensionSelectionLike | None = None, + height: datatypes.TensorDimensionSelectionLike | None = None, + indices: datatypes.TensorDimensionIndexSelectionArrayLike | None = None, + slider: blueprint_datatypes.TensorDimensionIndexSliderArrayLike | None = None, + ) -> TensorSliceSelection: + """ + Update only some specific fields of a `TensorSliceSelection`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + width: + Which dimension to map to width. + + If not specified, the height will be determined automatically based on the name and index of the dimension. + height: + Which dimension to map to height. + + If not specified, the height will be determined automatically based on the name and index of the dimension. + indices: + Selected indices for all other dimensions. + + If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. + slider: + Any dimension listed here will have a slider for the index. + + Edits to the sliders will directly manipulate dimensions on the `indices` list. + If any of the here listed dimensions is equal to `width` or `height`, it will be ignored. + If not specified, adds slides for any dimension in `indices`. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "width": width, + "height": height, + "indices": indices, + "slider": slider, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> TensorSliceSelection: + """Clear all the fields of a `TensorSliceSelection`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + width=[], + height=[], + indices=[], + slider=[], + ) + return inst + width: components.TensorWidthDimensionBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TensorWidthDimensionBatch._optional, # type: ignore[misc] + converter=components.TensorWidthDimensionBatch._converter, # type: ignore[misc] ) # Which dimension to map to width. # @@ -91,9 +159,9 @@ def _clear(cls) -> TensorSliceSelection: # (Docstring intentionally commented out to hide this field from the docs) height: components.TensorHeightDimensionBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TensorHeightDimensionBatch._optional, # type: ignore[misc] + converter=components.TensorHeightDimensionBatch._converter, # type: ignore[misc] ) # Which dimension to map to height. # @@ -102,9 +170,9 @@ def _clear(cls) -> TensorSliceSelection: # (Docstring intentionally commented out to hide this field from the docs) indices: components.TensorDimensionIndexSelectionBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.TensorDimensionIndexSelectionBatch._optional, # type: ignore[misc] + converter=components.TensorDimensionIndexSelectionBatch._converter, # type: ignore[misc] ) # Selected indices for all other dimensions. # @@ -113,9 +181,9 @@ def _clear(cls) -> TensorSliceSelection: # (Docstring intentionally commented out to hide this field from the docs) slider: blueprint_components.TensorDimensionIndexSliderBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.TensorDimensionIndexSliderBatch._optional, # type: ignore[misc] + converter=blueprint_components.TensorDimensionIndexSliderBatch._converter, # type: ignore[misc] ) # Any dimension listed here will have a slider for the index. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py index 7aa1c63ae1fa..17497eca5fd7 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/tensor_view_fit.py @@ -11,6 +11,7 @@ Archetype, ) from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions from .tensor_view_fit_ext import TensorViewFitExt __all__ = ["TensorViewFit"] @@ -25,7 +26,7 @@ class TensorViewFit(TensorViewFitExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - scaling=None, # type: ignore[arg-type] + scaling=None, ) @classmethod @@ -35,10 +36,53 @@ def _clear(cls) -> TensorViewFit: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + scaling: blueprint_components.ViewFitLike | None = None, + ) -> TensorViewFit: + """ + Update only some specific fields of a `TensorViewFit`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + scaling: + How the image is scaled to fit the view. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "scaling": scaling, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> TensorViewFit: + """Clear all the fields of a `TensorViewFit`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + scaling=[], + ) + return inst + scaling: blueprint_components.ViewFitBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ViewFitBatch._optional, # type: ignore[misc] + converter=blueprint_components.ViewFitBatch._converter, # type: ignore[misc] ) # How the image is scaled to fit the view. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py index 70ef957a1617..013cb30bd5fd 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_blueprint.py @@ -66,10 +66,10 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - class_identifier=None, # type: ignore[arg-type] - display_name=None, # type: ignore[arg-type] - space_origin=None, # type: ignore[arg-type] - visible=None, # type: ignore[arg-type] + class_identifier=None, + display_name=None, + space_origin=None, + visible=None, ) @classmethod @@ -79,27 +79,94 @@ def _clear(cls) -> ViewBlueprint: inst.__attrs_clear__() return inst - class_identifier: blueprint_components.ViewClassBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.ViewClassBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + class_identifier: datatypes.Utf8Like | None = None, + display_name: datatypes.Utf8Like | None = None, + space_origin: datatypes.EntityPathLike | None = None, + visible: datatypes.BoolLike | None = None, + ) -> ViewBlueprint: + """ + Update only some specific fields of a `ViewBlueprint`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + class_identifier: + The class of the view. + display_name: + The name of the view. + space_origin: + The "anchor point" of this view. + + Defaults to the root path '/' if not specified. + + The transform at this path forms the reference point for all scene->world transforms in this view. + I.e. the position of this entity path in space forms the origin of the coordinate system in this view. + Furthermore, this is the primary indicator for heuristics on what entities we show in this view. + visible: + Whether this view is visible. + + Defaults to true if not specified. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "class_identifier": class_identifier, + "display_name": display_name, + "space_origin": space_origin, + "visible": visible, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ViewBlueprint: + """Clear all the fields of a `ViewBlueprint`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + class_identifier=[], + display_name=[], + space_origin=[], + visible=[], + ) + return inst + + class_identifier: blueprint_components.ViewClassBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.ViewClassBatch._converter, # type: ignore[misc] ) # The class of the view. # # (Docstring intentionally commented out to hide this field from the docs) display_name: components.NameBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.NameBatch._optional, # type: ignore[misc] + converter=components.NameBatch._converter, # type: ignore[misc] ) # The name of the view. # # (Docstring intentionally commented out to hide this field from the docs) space_origin: blueprint_components.ViewOriginBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ViewOriginBatch._optional, # type: ignore[misc] + converter=blueprint_components.ViewOriginBatch._converter, # type: ignore[misc] ) # The "anchor point" of this view. # @@ -112,9 +179,9 @@ def _clear(cls) -> ViewBlueprint: # (Docstring intentionally commented out to hide this field from the docs) visible: blueprint_components.VisibleBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.VisibleBatch._optional, # type: ignore[misc] + converter=blueprint_components.VisibleBatch._converter, # type: ignore[misc] ) # Whether this view is visible. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py index 8708444a715a..2f9d6b2184fa 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/view_contents.py @@ -84,7 +84,7 @@ def __init__(self: Any, query: datatypes.Utf8ArrayLike): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - query=None, # type: ignore[arg-type] + query=None, ) @classmethod @@ -94,9 +94,55 @@ def _clear(cls) -> ViewContents: inst.__attrs_clear__() return inst - query: blueprint_components.QueryExpressionBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.QueryExpressionBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + query: datatypes.Utf8ArrayLike | None = None, + ) -> ViewContents: + """ + Update only some specific fields of a `ViewContents`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + query: + The `QueryExpression` that populates the contents for the view. + + They determine which entities are part of the view. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "query": query, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ViewContents: + """Clear all the fields of a `ViewContents`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + query=[], + ) + return inst + + query: blueprint_components.QueryExpressionBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.QueryExpressionBatch._converter, # type: ignore[misc] ) # The `QueryExpression` that populates the contents for the view. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py index 3c8e85ce7139..3fe08aea0b65 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py @@ -77,11 +77,11 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - root_container=None, # type: ignore[arg-type] - maximized=None, # type: ignore[arg-type] - auto_layout=None, # type: ignore[arg-type] - auto_views=None, # type: ignore[arg-type] - past_viewer_recommendations=None, # type: ignore[arg-type] + root_container=None, + maximized=None, + auto_layout=None, + auto_views=None, + past_viewer_recommendations=None, ) @classmethod @@ -91,28 +91,103 @@ def _clear(cls) -> ViewportBlueprint: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + root_container: datatypes.UuidLike | None = None, + maximized: datatypes.UuidLike | None = None, + auto_layout: datatypes.BoolLike | None = None, + auto_views: datatypes.BoolLike | None = None, + past_viewer_recommendations: datatypes.UInt64ArrayLike | None = None, + ) -> ViewportBlueprint: + """ + Update only some specific fields of a `ViewportBlueprint`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + root_container: + The layout of the views + maximized: + Show one tab as maximized? + auto_layout: + Whether the viewport layout is determined automatically. + + If `true`, the container layout will be reset whenever a new view is added or removed. + This defaults to `false` and is automatically set to `false` when there is user determined layout. + auto_views: + Whether or not views should be created automatically. + + If `true`, the viewer will only add views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + and which aren't deemed redundant to existing views. + This defaults to `false` and is automatically set to `false` when the user adds views manually in the viewer. + past_viewer_recommendations: + Hashes of all recommended views the viewer has already added and that should not be added again. + + This is an internal field and should not be set usually. + If you want the viewer from stopping to add views, you should set `auto_views` to `false`. + + The viewer uses this to determine whether it should keep adding views. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "root_container": root_container, + "maximized": maximized, + "auto_layout": auto_layout, + "auto_views": auto_views, + "past_viewer_recommendations": past_viewer_recommendations, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> ViewportBlueprint: + """Clear all the fields of a `ViewportBlueprint`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + root_container=[], + maximized=[], + auto_layout=[], + auto_views=[], + past_viewer_recommendations=[], + ) + return inst + root_container: blueprint_components.RootContainerBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.RootContainerBatch._optional, # type: ignore[misc] + converter=blueprint_components.RootContainerBatch._converter, # type: ignore[misc] ) # The layout of the views # # (Docstring intentionally commented out to hide this field from the docs) maximized: blueprint_components.ViewMaximizedBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ViewMaximizedBatch._optional, # type: ignore[misc] + converter=blueprint_components.ViewMaximizedBatch._converter, # type: ignore[misc] ) # Show one tab as maximized? # # (Docstring intentionally commented out to hide this field from the docs) auto_layout: blueprint_components.AutoLayoutBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.AutoLayoutBatch._optional, # type: ignore[misc] + converter=blueprint_components.AutoLayoutBatch._converter, # type: ignore[misc] ) # Whether the viewport layout is determined automatically. # @@ -122,9 +197,9 @@ def _clear(cls) -> ViewportBlueprint: # (Docstring intentionally commented out to hide this field from the docs) auto_views: blueprint_components.AutoViewsBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.AutoViewsBatch._optional, # type: ignore[misc] + converter=blueprint_components.AutoViewsBatch._converter, # type: ignore[misc] ) # Whether or not views should be created automatically. # @@ -135,9 +210,9 @@ def _clear(cls) -> ViewportBlueprint: # (Docstring intentionally commented out to hide this field from the docs) past_viewer_recommendations: blueprint_components.ViewerRecommendationHashBatch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=blueprint_components.ViewerRecommendationHashBatch._optional, # type: ignore[misc] + converter=blueprint_components.ViewerRecommendationHashBatch._converter, # type: ignore[misc] ) # Hashes of all recommended views the viewer has already added and that should not be added again. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py index 6554b67d55e4..3101d9f5dfb5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_ranges.py @@ -7,10 +7,12 @@ from attrs import define, field +from ... import datatypes from ..._baseclasses import ( Archetype, ) from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions from .visible_time_ranges_ext import VisibleTimeRangesExt __all__ = ["VisibleTimeRanges"] @@ -35,7 +37,7 @@ class VisibleTimeRanges(VisibleTimeRangesExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - ranges=None, # type: ignore[arg-type] + ranges=None, ) @classmethod @@ -45,9 +47,55 @@ def _clear(cls) -> VisibleTimeRanges: inst.__attrs_clear__() return inst - ranges: blueprint_components.VisibleTimeRangeBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.VisibleTimeRangeBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + ranges: datatypes.VisibleTimeRangeArrayLike | None = None, + ) -> VisibleTimeRanges: + """ + Update only some specific fields of a `VisibleTimeRanges`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + ranges: + The time ranges to show for each timeline unless specified otherwise on a per-entity basis. + + If a timeline is specified more than once, the first entry will be used. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "ranges": ranges, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> VisibleTimeRanges: + """Clear all the fields of a `VisibleTimeRanges`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + ranges=[], + ) + return inst + + ranges: blueprint_components.VisibleTimeRangeBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.VisibleTimeRangeBatch._converter, # type: ignore[misc] ) # The time ranges to show for each timeline unless specified otherwise on a per-entity basis. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py index 7a6a5159dc0b..16444fb54aa1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds2d.py @@ -7,10 +7,12 @@ from attrs import define, field +from ... import datatypes from ..._baseclasses import ( Archetype, ) from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions from .visual_bounds2d_ext import VisualBounds2DExt __all__ = ["VisualBounds2D"] @@ -33,7 +35,7 @@ class VisualBounds2D(VisualBounds2DExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - range=None, # type: ignore[arg-type] + range=None, ) @classmethod @@ -43,9 +45,55 @@ def _clear(cls) -> VisualBounds2D: inst.__attrs_clear__() return inst - range: blueprint_components.VisualBounds2DBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.VisualBounds2DBatch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + range: datatypes.Range2DLike | None = None, + ) -> VisualBounds2D: + """ + Update only some specific fields of a `VisualBounds2D`. + + Parameters + ---------- + clear: + If true, all unspecified fields will be explicitly cleared. + range: + Controls the visible range of a 2D view. + + Use this to control pan & zoom of the view. + + """ + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "range": range, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> VisualBounds2D: + """Clear all the fields of a `VisualBounds2D`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + range=[], + ) + return inst + + range: blueprint_components.VisualBounds2DBatch | None = field( + metadata={"component": True}, + default=None, + converter=blueprint_components.VisualBounds2DBatch._converter, # type: ignore[misc] ) # Controls the visible range of a 2D view. # diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py index 15a00291dbec..2b53b0966924 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py @@ -79,28 +79,28 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - fuzz1001=None, # type: ignore[arg-type] - fuzz1002=None, # type: ignore[arg-type] - fuzz1003=None, # type: ignore[arg-type] - fuzz1004=None, # type: ignore[arg-type] - fuzz1005=None, # type: ignore[arg-type] - fuzz1006=None, # type: ignore[arg-type] - fuzz1007=None, # type: ignore[arg-type] - fuzz1008=None, # type: ignore[arg-type] - fuzz1009=None, # type: ignore[arg-type] - fuzz1010=None, # type: ignore[arg-type] - fuzz1011=None, # type: ignore[arg-type] - fuzz1012=None, # type: ignore[arg-type] - fuzz1013=None, # type: ignore[arg-type] - fuzz1014=None, # type: ignore[arg-type] - fuzz1015=None, # type: ignore[arg-type] - fuzz1016=None, # type: ignore[arg-type] - fuzz1017=None, # type: ignore[arg-type] - fuzz1018=None, # type: ignore[arg-type] - fuzz1019=None, # type: ignore[arg-type] - fuzz1020=None, # type: ignore[arg-type] - fuzz1021=None, # type: ignore[arg-type] - fuzz1022=None, # type: ignore[arg-type] + fuzz1001=None, + fuzz1002=None, + fuzz1003=None, + fuzz1004=None, + fuzz1005=None, + fuzz1006=None, + fuzz1007=None, + fuzz1008=None, + fuzz1009=None, + fuzz1010=None, + fuzz1011=None, + fuzz1012=None, + fuzz1013=None, + fuzz1014=None, + fuzz1015=None, + fuzz1016=None, + fuzz1017=None, + fuzz1018=None, + fuzz1019=None, + fuzz1020=None, + fuzz1021=None, + fuzz1022=None, ) @classmethod @@ -110,93 +110,211 @@ def _clear(cls) -> AffixFuzzer1: inst.__attrs_clear__() return inst - fuzz1001: components.AffixFuzzer1Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer1Batch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + fuzz1001: datatypes.AffixFuzzer1Like | None = None, + fuzz1002: datatypes.AffixFuzzer1Like | None = None, + fuzz1003: datatypes.AffixFuzzer1Like | None = None, + fuzz1004: datatypes.AffixFuzzer1Like | None = None, + fuzz1005: datatypes.AffixFuzzer1Like | None = None, + fuzz1006: datatypes.AffixFuzzer1Like | None = None, + fuzz1007: components.AffixFuzzer7Like | None = None, + fuzz1008: components.AffixFuzzer8Like | None = None, + fuzz1009: components.AffixFuzzer9Like | None = None, + fuzz1010: components.AffixFuzzer10Like | None = None, + fuzz1011: components.AffixFuzzer11Like | None = None, + fuzz1012: components.AffixFuzzer12Like | None = None, + fuzz1013: components.AffixFuzzer13Like | None = None, + fuzz1014: datatypes.AffixFuzzer3Like | None = None, + fuzz1015: datatypes.AffixFuzzer3Like | None = None, + fuzz1016: components.AffixFuzzer16Like | None = None, + fuzz1017: components.AffixFuzzer17Like | None = None, + fuzz1018: components.AffixFuzzer18Like | None = None, + fuzz1019: datatypes.AffixFuzzer5Like | None = None, + fuzz1020: datatypes.AffixFuzzer20Like | None = None, + fuzz1021: datatypes.AffixFuzzer21Like | None = None, + fuzz1022: datatypes.AffixFuzzer22Like | None = None, + ) -> AffixFuzzer1: + """Update only some specific fields of a `AffixFuzzer1`.""" + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "fuzz1001": fuzz1001, + "fuzz1002": fuzz1002, + "fuzz1003": fuzz1003, + "fuzz1004": fuzz1004, + "fuzz1005": fuzz1005, + "fuzz1006": fuzz1006, + "fuzz1007": fuzz1007, + "fuzz1008": fuzz1008, + "fuzz1009": fuzz1009, + "fuzz1010": fuzz1010, + "fuzz1011": fuzz1011, + "fuzz1012": fuzz1012, + "fuzz1013": fuzz1013, + "fuzz1014": fuzz1014, + "fuzz1015": fuzz1015, + "fuzz1016": fuzz1016, + "fuzz1017": fuzz1017, + "fuzz1018": fuzz1018, + "fuzz1019": fuzz1019, + "fuzz1020": fuzz1020, + "fuzz1021": fuzz1021, + "fuzz1022": fuzz1022, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AffixFuzzer1: + """Clear all the fields of a `AffixFuzzer1`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + fuzz1001=[], + fuzz1002=[], + fuzz1003=[], + fuzz1004=[], + fuzz1005=[], + fuzz1006=[], + fuzz1007=[], + fuzz1008=[], + fuzz1009=[], + fuzz1010=[], + fuzz1011=[], + fuzz1012=[], + fuzz1013=[], + fuzz1014=[], + fuzz1015=[], + fuzz1016=[], + fuzz1017=[], + fuzz1018=[], + fuzz1019=[], + fuzz1020=[], + fuzz1021=[], + fuzz1022=[], + ) + return inst + + fuzz1001: components.AffixFuzzer1Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer1Batch._converter, # type: ignore[misc] ) - fuzz1002: components.AffixFuzzer2Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer2Batch._required, # type: ignore[misc] + fuzz1002: components.AffixFuzzer2Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer2Batch._converter, # type: ignore[misc] ) - fuzz1003: components.AffixFuzzer3Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer3Batch._required, # type: ignore[misc] + fuzz1003: components.AffixFuzzer3Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer3Batch._converter, # type: ignore[misc] ) - fuzz1004: components.AffixFuzzer4Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer4Batch._required, # type: ignore[misc] + fuzz1004: components.AffixFuzzer4Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer4Batch._converter, # type: ignore[misc] ) - fuzz1005: components.AffixFuzzer5Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer5Batch._required, # type: ignore[misc] + fuzz1005: components.AffixFuzzer5Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer5Batch._converter, # type: ignore[misc] ) - fuzz1006: components.AffixFuzzer6Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer6Batch._required, # type: ignore[misc] + fuzz1006: components.AffixFuzzer6Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer6Batch._converter, # type: ignore[misc] ) - fuzz1007: components.AffixFuzzer7Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer7Batch._required, # type: ignore[misc] + fuzz1007: components.AffixFuzzer7Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer7Batch._converter, # type: ignore[misc] ) - fuzz1008: components.AffixFuzzer8Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer8Batch._required, # type: ignore[misc] + fuzz1008: components.AffixFuzzer8Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer8Batch._converter, # type: ignore[misc] ) - fuzz1009: components.AffixFuzzer9Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer9Batch._required, # type: ignore[misc] + fuzz1009: components.AffixFuzzer9Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer9Batch._converter, # type: ignore[misc] ) - fuzz1010: components.AffixFuzzer10Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer10Batch._required, # type: ignore[misc] + fuzz1010: components.AffixFuzzer10Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer10Batch._converter, # type: ignore[misc] ) - fuzz1011: components.AffixFuzzer11Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer11Batch._required, # type: ignore[misc] + fuzz1011: components.AffixFuzzer11Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer11Batch._converter, # type: ignore[misc] ) - fuzz1012: components.AffixFuzzer12Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer12Batch._required, # type: ignore[misc] + fuzz1012: components.AffixFuzzer12Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer12Batch._converter, # type: ignore[misc] ) - fuzz1013: components.AffixFuzzer13Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer13Batch._required, # type: ignore[misc] + fuzz1013: components.AffixFuzzer13Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer13Batch._converter, # type: ignore[misc] ) - fuzz1014: components.AffixFuzzer14Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer14Batch._required, # type: ignore[misc] + fuzz1014: components.AffixFuzzer14Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer14Batch._converter, # type: ignore[misc] ) - fuzz1015: components.AffixFuzzer15Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer15Batch._required, # type: ignore[misc] + fuzz1015: components.AffixFuzzer15Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer15Batch._converter, # type: ignore[misc] ) - fuzz1016: components.AffixFuzzer16Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer16Batch._required, # type: ignore[misc] + fuzz1016: components.AffixFuzzer16Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer16Batch._converter, # type: ignore[misc] ) - fuzz1017: components.AffixFuzzer17Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer17Batch._required, # type: ignore[misc] + fuzz1017: components.AffixFuzzer17Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer17Batch._converter, # type: ignore[misc] ) - fuzz1018: components.AffixFuzzer18Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer18Batch._required, # type: ignore[misc] + fuzz1018: components.AffixFuzzer18Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer18Batch._converter, # type: ignore[misc] ) - fuzz1019: components.AffixFuzzer19Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer19Batch._required, # type: ignore[misc] + fuzz1019: components.AffixFuzzer19Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer19Batch._converter, # type: ignore[misc] ) - fuzz1020: components.AffixFuzzer20Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer20Batch._required, # type: ignore[misc] + fuzz1020: components.AffixFuzzer20Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer20Batch._converter, # type: ignore[misc] ) - fuzz1021: components.AffixFuzzer21Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer21Batch._required, # type: ignore[misc] + fuzz1021: components.AffixFuzzer21Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer21Batch._converter, # type: ignore[misc] ) - fuzz1022: components.AffixFuzzer22Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer22Batch._required, # type: ignore[misc] + fuzz1022: components.AffixFuzzer22Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer22Batch._converter, # type: ignore[misc] ) __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py index cdfbb6005b05..6d1c623d2ec2 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py @@ -73,25 +73,25 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - fuzz1101=None, # type: ignore[arg-type] - fuzz1102=None, # type: ignore[arg-type] - fuzz1103=None, # type: ignore[arg-type] - fuzz1104=None, # type: ignore[arg-type] - fuzz1105=None, # type: ignore[arg-type] - fuzz1106=None, # type: ignore[arg-type] - fuzz1107=None, # type: ignore[arg-type] - fuzz1108=None, # type: ignore[arg-type] - fuzz1109=None, # type: ignore[arg-type] - fuzz1110=None, # type: ignore[arg-type] - fuzz1111=None, # type: ignore[arg-type] - fuzz1112=None, # type: ignore[arg-type] - fuzz1113=None, # type: ignore[arg-type] - fuzz1114=None, # type: ignore[arg-type] - fuzz1115=None, # type: ignore[arg-type] - fuzz1116=None, # type: ignore[arg-type] - fuzz1117=None, # type: ignore[arg-type] - fuzz1118=None, # type: ignore[arg-type] - fuzz1122=None, # type: ignore[arg-type] + fuzz1101=None, + fuzz1102=None, + fuzz1103=None, + fuzz1104=None, + fuzz1105=None, + fuzz1106=None, + fuzz1107=None, + fuzz1108=None, + fuzz1109=None, + fuzz1110=None, + fuzz1111=None, + fuzz1112=None, + fuzz1113=None, + fuzz1114=None, + fuzz1115=None, + fuzz1116=None, + fuzz1117=None, + fuzz1118=None, + fuzz1122=None, ) @classmethod @@ -101,81 +101,187 @@ def _clear(cls) -> AffixFuzzer2: inst.__attrs_clear__() return inst - fuzz1101: components.AffixFuzzer1Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer1Batch._required, # type: ignore[misc] + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + fuzz1101: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1102: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1103: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1104: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1105: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1106: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz1107: components.AffixFuzzer7ArrayLike | None = None, + fuzz1108: components.AffixFuzzer8ArrayLike | None = None, + fuzz1109: components.AffixFuzzer9ArrayLike | None = None, + fuzz1110: components.AffixFuzzer10ArrayLike | None = None, + fuzz1111: components.AffixFuzzer11ArrayLike | None = None, + fuzz1112: components.AffixFuzzer12ArrayLike | None = None, + fuzz1113: components.AffixFuzzer13ArrayLike | None = None, + fuzz1114: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1115: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz1116: components.AffixFuzzer16ArrayLike | None = None, + fuzz1117: components.AffixFuzzer17ArrayLike | None = None, + fuzz1118: components.AffixFuzzer18ArrayLike | None = None, + fuzz1122: datatypes.AffixFuzzer22ArrayLike | None = None, + ) -> AffixFuzzer2: + """Update only some specific fields of a `AffixFuzzer2`.""" + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "fuzz1101": fuzz1101, + "fuzz1102": fuzz1102, + "fuzz1103": fuzz1103, + "fuzz1104": fuzz1104, + "fuzz1105": fuzz1105, + "fuzz1106": fuzz1106, + "fuzz1107": fuzz1107, + "fuzz1108": fuzz1108, + "fuzz1109": fuzz1109, + "fuzz1110": fuzz1110, + "fuzz1111": fuzz1111, + "fuzz1112": fuzz1112, + "fuzz1113": fuzz1113, + "fuzz1114": fuzz1114, + "fuzz1115": fuzz1115, + "fuzz1116": fuzz1116, + "fuzz1117": fuzz1117, + "fuzz1118": fuzz1118, + "fuzz1122": fuzz1122, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AffixFuzzer2: + """Clear all the fields of a `AffixFuzzer2`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + fuzz1101=[], + fuzz1102=[], + fuzz1103=[], + fuzz1104=[], + fuzz1105=[], + fuzz1106=[], + fuzz1107=[], + fuzz1108=[], + fuzz1109=[], + fuzz1110=[], + fuzz1111=[], + fuzz1112=[], + fuzz1113=[], + fuzz1114=[], + fuzz1115=[], + fuzz1116=[], + fuzz1117=[], + fuzz1118=[], + fuzz1122=[], + ) + return inst + + fuzz1101: components.AffixFuzzer1Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer1Batch._converter, # type: ignore[misc] ) - fuzz1102: components.AffixFuzzer2Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer2Batch._required, # type: ignore[misc] + fuzz1102: components.AffixFuzzer2Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer2Batch._converter, # type: ignore[misc] ) - fuzz1103: components.AffixFuzzer3Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer3Batch._required, # type: ignore[misc] + fuzz1103: components.AffixFuzzer3Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer3Batch._converter, # type: ignore[misc] ) - fuzz1104: components.AffixFuzzer4Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer4Batch._required, # type: ignore[misc] + fuzz1104: components.AffixFuzzer4Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer4Batch._converter, # type: ignore[misc] ) - fuzz1105: components.AffixFuzzer5Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer5Batch._required, # type: ignore[misc] + fuzz1105: components.AffixFuzzer5Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer5Batch._converter, # type: ignore[misc] ) - fuzz1106: components.AffixFuzzer6Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer6Batch._required, # type: ignore[misc] + fuzz1106: components.AffixFuzzer6Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer6Batch._converter, # type: ignore[misc] ) - fuzz1107: components.AffixFuzzer7Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer7Batch._required, # type: ignore[misc] + fuzz1107: components.AffixFuzzer7Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer7Batch._converter, # type: ignore[misc] ) - fuzz1108: components.AffixFuzzer8Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer8Batch._required, # type: ignore[misc] + fuzz1108: components.AffixFuzzer8Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer8Batch._converter, # type: ignore[misc] ) - fuzz1109: components.AffixFuzzer9Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer9Batch._required, # type: ignore[misc] + fuzz1109: components.AffixFuzzer9Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer9Batch._converter, # type: ignore[misc] ) - fuzz1110: components.AffixFuzzer10Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer10Batch._required, # type: ignore[misc] + fuzz1110: components.AffixFuzzer10Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer10Batch._converter, # type: ignore[misc] ) - fuzz1111: components.AffixFuzzer11Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer11Batch._required, # type: ignore[misc] + fuzz1111: components.AffixFuzzer11Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer11Batch._converter, # type: ignore[misc] ) - fuzz1112: components.AffixFuzzer12Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer12Batch._required, # type: ignore[misc] + fuzz1112: components.AffixFuzzer12Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer12Batch._converter, # type: ignore[misc] ) - fuzz1113: components.AffixFuzzer13Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer13Batch._required, # type: ignore[misc] + fuzz1113: components.AffixFuzzer13Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer13Batch._converter, # type: ignore[misc] ) - fuzz1114: components.AffixFuzzer14Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer14Batch._required, # type: ignore[misc] + fuzz1114: components.AffixFuzzer14Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer14Batch._converter, # type: ignore[misc] ) - fuzz1115: components.AffixFuzzer15Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer15Batch._required, # type: ignore[misc] + fuzz1115: components.AffixFuzzer15Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer15Batch._converter, # type: ignore[misc] ) - fuzz1116: components.AffixFuzzer16Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer16Batch._required, # type: ignore[misc] + fuzz1116: components.AffixFuzzer16Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer16Batch._converter, # type: ignore[misc] ) - fuzz1117: components.AffixFuzzer17Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer17Batch._required, # type: ignore[misc] + fuzz1117: components.AffixFuzzer17Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer17Batch._converter, # type: ignore[misc] ) - fuzz1118: components.AffixFuzzer18Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer18Batch._required, # type: ignore[misc] + fuzz1118: components.AffixFuzzer18Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer18Batch._converter, # type: ignore[misc] ) - fuzz1122: components.AffixFuzzer22Batch = field( - metadata={"component": "required"}, - converter=components.AffixFuzzer22Batch._required, # type: ignore[misc] + fuzz1122: components.AffixFuzzer22Batch | None = field( + metadata={"component": True}, + default=None, + converter=components.AffixFuzzer22Batch._converter, # type: ignore[misc] ) __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py index d1f7dfd6ade7..a78d6215b144 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py @@ -72,24 +72,24 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - fuzz2001=None, # type: ignore[arg-type] - fuzz2002=None, # type: ignore[arg-type] - fuzz2003=None, # type: ignore[arg-type] - fuzz2004=None, # type: ignore[arg-type] - fuzz2005=None, # type: ignore[arg-type] - fuzz2006=None, # type: ignore[arg-type] - fuzz2007=None, # type: ignore[arg-type] - fuzz2008=None, # type: ignore[arg-type] - fuzz2009=None, # type: ignore[arg-type] - fuzz2010=None, # type: ignore[arg-type] - fuzz2011=None, # type: ignore[arg-type] - fuzz2012=None, # type: ignore[arg-type] - fuzz2013=None, # type: ignore[arg-type] - fuzz2014=None, # type: ignore[arg-type] - fuzz2015=None, # type: ignore[arg-type] - fuzz2016=None, # type: ignore[arg-type] - fuzz2017=None, # type: ignore[arg-type] - fuzz2018=None, # type: ignore[arg-type] + fuzz2001=None, + fuzz2002=None, + fuzz2003=None, + fuzz2004=None, + fuzz2005=None, + fuzz2006=None, + fuzz2007=None, + fuzz2008=None, + fuzz2009=None, + fuzz2010=None, + fuzz2011=None, + fuzz2012=None, + fuzz2013=None, + fuzz2014=None, + fuzz2015=None, + fuzz2016=None, + fuzz2017=None, + fuzz2018=None, ) @classmethod @@ -99,95 +99,179 @@ def _clear(cls) -> AffixFuzzer3: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + fuzz2001: datatypes.AffixFuzzer1Like | None = None, + fuzz2002: datatypes.AffixFuzzer1Like | None = None, + fuzz2003: datatypes.AffixFuzzer1Like | None = None, + fuzz2004: datatypes.AffixFuzzer1Like | None = None, + fuzz2005: datatypes.AffixFuzzer1Like | None = None, + fuzz2006: datatypes.AffixFuzzer1Like | None = None, + fuzz2007: components.AffixFuzzer7Like | None = None, + fuzz2008: components.AffixFuzzer8Like | None = None, + fuzz2009: components.AffixFuzzer9Like | None = None, + fuzz2010: components.AffixFuzzer10Like | None = None, + fuzz2011: components.AffixFuzzer11Like | None = None, + fuzz2012: components.AffixFuzzer12Like | None = None, + fuzz2013: components.AffixFuzzer13Like | None = None, + fuzz2014: datatypes.AffixFuzzer3Like | None = None, + fuzz2015: datatypes.AffixFuzzer3Like | None = None, + fuzz2016: components.AffixFuzzer16Like | None = None, + fuzz2017: components.AffixFuzzer17Like | None = None, + fuzz2018: components.AffixFuzzer18Like | None = None, + ) -> AffixFuzzer3: + """Update only some specific fields of a `AffixFuzzer3`.""" + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "fuzz2001": fuzz2001, + "fuzz2002": fuzz2002, + "fuzz2003": fuzz2003, + "fuzz2004": fuzz2004, + "fuzz2005": fuzz2005, + "fuzz2006": fuzz2006, + "fuzz2007": fuzz2007, + "fuzz2008": fuzz2008, + "fuzz2009": fuzz2009, + "fuzz2010": fuzz2010, + "fuzz2011": fuzz2011, + "fuzz2012": fuzz2012, + "fuzz2013": fuzz2013, + "fuzz2014": fuzz2014, + "fuzz2015": fuzz2015, + "fuzz2016": fuzz2016, + "fuzz2017": fuzz2017, + "fuzz2018": fuzz2018, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AffixFuzzer3: + """Clear all the fields of a `AffixFuzzer3`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + fuzz2001=[], + fuzz2002=[], + fuzz2003=[], + fuzz2004=[], + fuzz2005=[], + fuzz2006=[], + fuzz2007=[], + fuzz2008=[], + fuzz2009=[], + fuzz2010=[], + fuzz2011=[], + fuzz2012=[], + fuzz2013=[], + fuzz2014=[], + fuzz2015=[], + fuzz2016=[], + fuzz2017=[], + fuzz2018=[], + ) + return inst + fuzz2001: components.AffixFuzzer1Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer1Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer1Batch._converter, # type: ignore[misc] ) fuzz2002: components.AffixFuzzer2Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer2Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer2Batch._converter, # type: ignore[misc] ) fuzz2003: components.AffixFuzzer3Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer3Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer3Batch._converter, # type: ignore[misc] ) fuzz2004: components.AffixFuzzer4Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer4Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer4Batch._converter, # type: ignore[misc] ) fuzz2005: components.AffixFuzzer5Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer5Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer5Batch._converter, # type: ignore[misc] ) fuzz2006: components.AffixFuzzer6Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer6Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer6Batch._converter, # type: ignore[misc] ) fuzz2007: components.AffixFuzzer7Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer7Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer7Batch._converter, # type: ignore[misc] ) fuzz2008: components.AffixFuzzer8Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer8Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer8Batch._converter, # type: ignore[misc] ) fuzz2009: components.AffixFuzzer9Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer9Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer9Batch._converter, # type: ignore[misc] ) fuzz2010: components.AffixFuzzer10Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer10Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer10Batch._converter, # type: ignore[misc] ) fuzz2011: components.AffixFuzzer11Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer11Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer11Batch._converter, # type: ignore[misc] ) fuzz2012: components.AffixFuzzer12Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer12Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer12Batch._converter, # type: ignore[misc] ) fuzz2013: components.AffixFuzzer13Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer13Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer13Batch._converter, # type: ignore[misc] ) fuzz2014: components.AffixFuzzer14Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer14Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer14Batch._converter, # type: ignore[misc] ) fuzz2015: components.AffixFuzzer15Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer15Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer15Batch._converter, # type: ignore[misc] ) fuzz2016: components.AffixFuzzer16Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer16Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer16Batch._converter, # type: ignore[misc] ) fuzz2017: components.AffixFuzzer17Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer17Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer17Batch._converter, # type: ignore[misc] ) fuzz2018: components.AffixFuzzer18Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer18Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer18Batch._converter, # type: ignore[misc] ) __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py index eab5407e1cf7..0dd2c12241f0 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py @@ -72,24 +72,24 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - fuzz2101=None, # type: ignore[arg-type] - fuzz2102=None, # type: ignore[arg-type] - fuzz2103=None, # type: ignore[arg-type] - fuzz2104=None, # type: ignore[arg-type] - fuzz2105=None, # type: ignore[arg-type] - fuzz2106=None, # type: ignore[arg-type] - fuzz2107=None, # type: ignore[arg-type] - fuzz2108=None, # type: ignore[arg-type] - fuzz2109=None, # type: ignore[arg-type] - fuzz2110=None, # type: ignore[arg-type] - fuzz2111=None, # type: ignore[arg-type] - fuzz2112=None, # type: ignore[arg-type] - fuzz2113=None, # type: ignore[arg-type] - fuzz2114=None, # type: ignore[arg-type] - fuzz2115=None, # type: ignore[arg-type] - fuzz2116=None, # type: ignore[arg-type] - fuzz2117=None, # type: ignore[arg-type] - fuzz2118=None, # type: ignore[arg-type] + fuzz2101=None, + fuzz2102=None, + fuzz2103=None, + fuzz2104=None, + fuzz2105=None, + fuzz2106=None, + fuzz2107=None, + fuzz2108=None, + fuzz2109=None, + fuzz2110=None, + fuzz2111=None, + fuzz2112=None, + fuzz2113=None, + fuzz2114=None, + fuzz2115=None, + fuzz2116=None, + fuzz2117=None, + fuzz2118=None, ) @classmethod @@ -99,95 +99,179 @@ def _clear(cls) -> AffixFuzzer4: inst.__attrs_clear__() return inst + @classmethod + def update_fields( + cls, + *, + clear: bool = False, + fuzz2101: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2102: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2103: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2104: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2105: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2106: datatypes.AffixFuzzer1ArrayLike | None = None, + fuzz2107: components.AffixFuzzer7ArrayLike | None = None, + fuzz2108: components.AffixFuzzer8ArrayLike | None = None, + fuzz2109: components.AffixFuzzer9ArrayLike | None = None, + fuzz2110: components.AffixFuzzer10ArrayLike | None = None, + fuzz2111: components.AffixFuzzer11ArrayLike | None = None, + fuzz2112: components.AffixFuzzer12ArrayLike | None = None, + fuzz2113: components.AffixFuzzer13ArrayLike | None = None, + fuzz2114: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2115: datatypes.AffixFuzzer3ArrayLike | None = None, + fuzz2116: components.AffixFuzzer16ArrayLike | None = None, + fuzz2117: components.AffixFuzzer17ArrayLike | None = None, + fuzz2118: components.AffixFuzzer18ArrayLike | None = None, + ) -> AffixFuzzer4: + """Update only some specific fields of a `AffixFuzzer4`.""" + + inst = cls.__new__(cls) + with catch_and_log_exceptions(context=cls.__name__): + kwargs = { + "fuzz2101": fuzz2101, + "fuzz2102": fuzz2102, + "fuzz2103": fuzz2103, + "fuzz2104": fuzz2104, + "fuzz2105": fuzz2105, + "fuzz2106": fuzz2106, + "fuzz2107": fuzz2107, + "fuzz2108": fuzz2108, + "fuzz2109": fuzz2109, + "fuzz2110": fuzz2110, + "fuzz2111": fuzz2111, + "fuzz2112": fuzz2112, + "fuzz2113": fuzz2113, + "fuzz2114": fuzz2114, + "fuzz2115": fuzz2115, + "fuzz2116": fuzz2116, + "fuzz2117": fuzz2117, + "fuzz2118": fuzz2118, + } + + if clear: + kwargs = {k: v if v is not None else [] for k, v in kwargs.items()} # type: ignore[misc] + + inst.__attrs_init__(**kwargs) + return inst + + inst.__attrs_clear__() + return inst + + @classmethod + def clear_fields(cls) -> AffixFuzzer4: + """Clear all the fields of a `AffixFuzzer4`.""" + inst = cls.__new__(cls) + inst.__attrs_init__( + fuzz2101=[], + fuzz2102=[], + fuzz2103=[], + fuzz2104=[], + fuzz2105=[], + fuzz2106=[], + fuzz2107=[], + fuzz2108=[], + fuzz2109=[], + fuzz2110=[], + fuzz2111=[], + fuzz2112=[], + fuzz2113=[], + fuzz2114=[], + fuzz2115=[], + fuzz2116=[], + fuzz2117=[], + fuzz2118=[], + ) + return inst + fuzz2101: components.AffixFuzzer1Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer1Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer1Batch._converter, # type: ignore[misc] ) fuzz2102: components.AffixFuzzer2Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer2Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer2Batch._converter, # type: ignore[misc] ) fuzz2103: components.AffixFuzzer3Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer3Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer3Batch._converter, # type: ignore[misc] ) fuzz2104: components.AffixFuzzer4Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer4Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer4Batch._converter, # type: ignore[misc] ) fuzz2105: components.AffixFuzzer5Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer5Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer5Batch._converter, # type: ignore[misc] ) fuzz2106: components.AffixFuzzer6Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer6Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer6Batch._converter, # type: ignore[misc] ) fuzz2107: components.AffixFuzzer7Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer7Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer7Batch._converter, # type: ignore[misc] ) fuzz2108: components.AffixFuzzer8Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer8Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer8Batch._converter, # type: ignore[misc] ) fuzz2109: components.AffixFuzzer9Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer9Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer9Batch._converter, # type: ignore[misc] ) fuzz2110: components.AffixFuzzer10Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer10Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer10Batch._converter, # type: ignore[misc] ) fuzz2111: components.AffixFuzzer11Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer11Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer11Batch._converter, # type: ignore[misc] ) fuzz2112: components.AffixFuzzer12Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer12Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer12Batch._converter, # type: ignore[misc] ) fuzz2113: components.AffixFuzzer13Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer13Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer13Batch._converter, # type: ignore[misc] ) fuzz2114: components.AffixFuzzer14Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer14Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer14Batch._converter, # type: ignore[misc] ) fuzz2115: components.AffixFuzzer15Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer15Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer15Batch._converter, # type: ignore[misc] ) fuzz2116: components.AffixFuzzer16Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer16Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer16Batch._converter, # type: ignore[misc] ) fuzz2117: components.AffixFuzzer17Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer17Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer17Batch._converter, # type: ignore[misc] ) fuzz2118: components.AffixFuzzer18Batch | None = field( - metadata={"component": "optional"}, + metadata={"component": True}, default=None, - converter=components.AffixFuzzer18Batch._optional, # type: ignore[misc] + converter=components.AffixFuzzer18Batch._converter, # type: ignore[misc] ) __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/tests/unit/common_arrays.py b/rerun_py/tests/unit/common_arrays.py index 7edb7235632f..a5e19fd21dcb 100644 --- a/rerun_py/tests/unit/common_arrays.py +++ b/rerun_py/tests/unit/common_arrays.py @@ -102,7 +102,7 @@ def dvec2ds_expected(obj: Any, type_: Any | None = None) -> Any: expected = none_empty_or_value(obj, [[1.0, 2.0], [3.0, 4.0]]) - return type_._optional(expected) + return type_._converter(expected) vec2ds_arrays: list[Vec2DArrayLike] = [ @@ -141,7 +141,7 @@ def vec2ds_expected(obj: Any, type_: Any | None = None) -> Any: expected = none_empty_or_value(obj, [[1.0, 2.0], [3.0, 4.0]]) - return type_._optional(expected) + return type_._converter(expected) vec3ds_arrays: list[Vec3DArrayLike] = [ @@ -180,7 +180,7 @@ def vec3ds_expected(obj: Any, type_: Any | None = None) -> Any: expected = none_empty_or_value(obj, [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) - return type_._optional(expected) + return type_._converter(expected) vec4ds_arrays: list[Vec4DArrayLike] = [ @@ -219,7 +219,7 @@ def vec4ds_expected(obj: Any, type_: Any | None = None) -> Any: expected = none_empty_or_value(obj, [[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0]]) - return type_._optional(expected) + return type_._converter(expected) uvec3ds_arrays: list[UVec3DArrayLike] = [ @@ -254,7 +254,7 @@ def uvec3ds_expected(obj: Any, type_: Any | None = None) -> Any: expected = none_empty_or_value(obj, [[1, 2, 3], [4, 5, 6]]) - return type_._optional(expected) + return type_._converter(expected) quaternions_arrays: list[QuaternionArrayLike] = [ @@ -274,13 +274,13 @@ def uvec3ds_expected(obj: Any, type_: Any | None = None) -> Any: def quaternions_expected(rotations: QuaternionArrayLike, type_: Any) -> Any: if rotations is None: - return type_._optional(None) + return type_._converter(None) elif hasattr(rotations, "__len__") and len(rotations) == 0: # type: ignore[arg-type] - return type_._optional(rotations) + return type_._converter(rotations) elif isinstance(rotations, Quaternion): - return type_._optional(Quaternion(xyzw=[1, 2, 3, 4])) + return type_._converter(Quaternion(xyzw=[1, 2, 3, 4])) else: # sequence of Rotation3DLike - return type_._optional([Quaternion(xyzw=[1, 2, 3, 4])] * 2) + return type_._converter([Quaternion(xyzw=[1, 2, 3, 4])] * 2) rotation_axis_angle_arrays: list[RotationAxisAngleArrayLike] = [ @@ -299,15 +299,15 @@ def quaternions_expected(rotations: QuaternionArrayLike, type_: Any) -> Any: def expected_rotation_axis_angles(rotations: RotationAxisAngleArrayLike, type_: Any) -> Any: if rotations is None: - return type_._optional(None) + return type_._converter(None) elif hasattr(rotations, "__len__") and len(rotations) == 0: - return type_._optional(rotations) + return type_._converter(rotations) elif isinstance(rotations, RotationAxisAngle): - return type_._optional(RotationAxisAngle([1, 2, 3], 4)) + return type_._converter(RotationAxisAngle([1, 2, 3], 4)) elif isinstance(rotations, Quaternion): - return type_._optional(Quaternion(xyzw=[1, 2, 3, 4])) + return type_._converter(Quaternion(xyzw=[1, 2, 3, 4])) else: # sequence of Rotation3DLike - return type_._optional([RotationAxisAngle([1, 2, 3], 4)] * 2) + return type_._converter([RotationAxisAngle([1, 2, 3], 4)] * 2) radii_arrays: list[Float32ArrayLike | None] = [ @@ -329,7 +329,7 @@ def expected_rotation_axis_angles(rotations: RotationAxisAngleArrayLike, type_: def radii_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, [1, 10]) - return RadiusBatch._optional(expected) + return RadiusBatch._converter(expected) colors_arrays: list[Rgba32ArrayLike | None] = [ @@ -441,7 +441,7 @@ def radii_expected(obj: Any) -> Any: def colors_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, [0xAA0000CC, 0x00BB00DD]) - return ColorBatch._optional(expected) + return ColorBatch._converter(expected) labels_arrays: list[Utf8ArrayLike | None] = [ @@ -459,7 +459,7 @@ def colors_expected(obj: Any) -> Any: def labels_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, ["hello", "friend"]) - return TextBatch._optional(expected) + return TextBatch._converter(expected) draw_orders: list[Float32ArrayLike | None] = [ @@ -473,7 +473,7 @@ def labels_expected(obj: Any) -> Any: def draw_order_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, [300]) - return DrawOrderBatch._optional(expected) + return DrawOrderBatch._converter(expected) class_ids_arrays = [ @@ -498,7 +498,7 @@ def draw_order_expected(obj: Any) -> Any: def class_ids_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, [126, 127]) - return ClassIdBatch._optional(expected) + return ClassIdBatch._converter(expected) keypoint_ids_arrays = [ @@ -523,7 +523,7 @@ def class_ids_expected(obj: Any) -> Any: def keypoint_ids_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, [2, 3]) - return KeypointIdBatch._optional(expected) + return KeypointIdBatch._converter(expected) uuid_bytes0 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] diff --git a/rerun_py/tests/unit/test_asset3d.py b/rerun_py/tests/unit/test_asset3d.py index b132c5a1547d..70a1f5959eb7 100644 --- a/rerun_py/tests/unit/test_asset3d.py +++ b/rerun_py/tests/unit/test_asset3d.py @@ -24,5 +24,8 @@ def test_asset3d() -> None: ] for asset in assets: - assert asset.blob.as_arrow_array() == rr.components.BlobBatch(blob_comp).as_arrow_array() + assert ( + asset.blob is not None + and asset.blob.as_arrow_array() == rr.components.BlobBatch(blob_comp).as_arrow_array() + ) assert asset.media_type == rr.components.MediaTypeBatch(rr.components.MediaType.GLB) diff --git a/rerun_py/tests/unit/test_box3d.py b/rerun_py/tests/unit/test_box3d.py index e78537829796..3f78c52c13be 100644 --- a/rerun_py/tests/unit/test_box3d.py +++ b/rerun_py/tests/unit/test_box3d.py @@ -113,7 +113,7 @@ def test_boxes3d() -> None: assert arch.quaternions == quaternions_expected(quaternions, PoseRotationQuatBatch) assert arch.colors == colors_expected(colors) assert arch.radii == radii_expected(radii) - assert arch.fill_mode == rr.components.FillModeBatch._optional(fill_mode) + assert arch.fill_mode == rr.components.FillModeBatch._converter(fill_mode) assert arch.labels == labels_expected(labels) assert arch.class_ids == class_ids_expected(class_ids) diff --git a/rerun_py/tests/unit/test_container_blueprint.py b/rerun_py/tests/unit/test_container_blueprint.py index 494644d7e970..90be9ab2ee2a 100644 --- a/rerun_py/tests/unit/test_container_blueprint.py +++ b/rerun_py/tests/unit/test_container_blueprint.py @@ -127,15 +127,15 @@ def test_container_blueprint() -> None: ) print(f"{arch}\n") - assert arch.container_kind == ContainerKindBatch._required( + assert arch.container_kind == ContainerKindBatch._converter( none_empty_or_value(container_kind, ContainerKind.Tabs) ) - assert arch.display_name == NameBatch._optional(none_empty_or_value(display_name, Name("my container"))) - assert arch.contents == IncludedContentBatch._optional(none_empty_or_value(contents, contents_arrays[-1])) - assert arch.col_shares == ColumnShareBatch._optional(none_empty_or_value(col_shares, col_shares_arrays[-1])) - assert arch.row_shares == RowShareBatch._optional(none_empty_or_value(row_shares, row_shares_arrays[-1])) - assert arch.active_tab == ActiveTabBatch._optional(none_empty_or_value(active_tab, active_tab_arrays[-1])) - assert arch.visible == VisibleBatch._optional(none_empty_or_value(visible, visible_arrays[-1])) - assert arch.grid_columns == GridColumnsBatch._optional( + assert arch.display_name == NameBatch._converter(none_empty_or_value(display_name, Name("my container"))) + assert arch.contents == IncludedContentBatch._converter(none_empty_or_value(contents, contents_arrays[-1])) + assert arch.col_shares == ColumnShareBatch._converter(none_empty_or_value(col_shares, col_shares_arrays[-1])) + assert arch.row_shares == RowShareBatch._converter(none_empty_or_value(row_shares, row_shares_arrays[-1])) + assert arch.active_tab == ActiveTabBatch._converter(none_empty_or_value(active_tab, active_tab_arrays[-1])) + assert arch.visible == VisibleBatch._converter(none_empty_or_value(visible, visible_arrays[-1])) + assert arch.grid_columns == GridColumnsBatch._converter( none_empty_or_value(grid_columns, grid_columns_arrays[-1]) ) diff --git a/rerun_py/tests/unit/test_depth_image.py b/rerun_py/tests/unit/test_depth_image.py index 3413901fc401..d6f58a02d590 100644 --- a/rerun_py/tests/unit/test_depth_image.py +++ b/rerun_py/tests/unit/test_depth_image.py @@ -13,7 +13,6 @@ rng = np.random.default_rng(12345) RANDOM_IMAGE_SOURCE = rng.uniform(0.0, 1.0, (10, 20)) - IMAGE_INPUTS: list[Any] = [ RANDOM_IMAGE_SOURCE, RANDOM_IMAGE_SOURCE, @@ -42,16 +41,16 @@ def test_depth_image() -> None: ) arch = rr.DepthImage(img, meter=meter, depth_range=depth_range) - assert arch.buffer == rr.components.ImageBufferBatch._optional(img.tobytes()) - assert arch.format == rr.components.ImageFormatBatch._optional( + assert arch.buffer == rr.components.ImageBufferBatch._converter(img.tobytes()) + assert arch.format == rr.components.ImageFormatBatch._converter( ImageFormat( width=img.shape[1], height=img.shape[0], channel_datatype=ChannelDatatype.from_np_dtype(img.dtype), ) ) - assert arch.meter == rr.components.DepthMeterBatch._optional(meter) - assert arch.depth_range == rr.components.ValueRangeBatch._optional(depth_range) + assert arch.meter == rr.components.DepthMeterBatch._converter(meter) + assert arch.depth_range == rr.components.ValueRangeBatch._converter(depth_range) GOOD_IMAGE_INPUTS: list[Any] = [ diff --git a/rerun_py/tests/unit/test_ellipsoids3d.py b/rerun_py/tests/unit/test_ellipsoids3d.py index d500b3ea5c26..b7542a852248 100644 --- a/rerun_py/tests/unit/test_ellipsoids3d.py +++ b/rerun_py/tests/unit/test_ellipsoids3d.py @@ -113,6 +113,6 @@ def test_ellipsoids() -> None: assert arch.quaternions == quaternions_expected(quaternions, PoseRotationQuatBatch) assert arch.colors == colors_expected(colors) assert arch.line_radii == radii_expected(line_radii) - assert arch.fill_mode == rr.components.FillModeBatch._optional(fill_mode) + assert arch.fill_mode == rr.components.FillModeBatch._converter(fill_mode) assert arch.labels == labels_expected(labels) assert arch.class_ids == class_ids_expected(class_ids) diff --git a/rerun_py/tests/unit/test_exceptions.py b/rerun_py/tests/unit/test_exceptions.py index 3ffd72d896c8..e0d607825454 100644 --- a/rerun_py/tests/unit/test_exceptions.py +++ b/rerun_py/tests/unit/test_exceptions.py @@ -143,8 +143,8 @@ def test_bad_components() -> None: with pytest.warns(RerunWarning) as warnings: points = rr.Points3D(positions=[1, 2, 3], colors="RED") assert len(warnings) == 1 - assert len(points.positions) == 1 - assert len(points.colors) == 0 # type: ignore[arg-type] + assert points.positions is not None and len(points.positions) == 1 + assert points.colors is not None and len(points.colors) == 0 rr.set_strict_mode(True) with pytest.raises(ValueError): diff --git a/rerun_py/tests/unit/test_geo_line_strings.py b/rerun_py/tests/unit/test_geo_line_strings.py index bd755aeca8f9..be2c728fa590 100644 --- a/rerun_py/tests/unit/test_geo_line_strings.py +++ b/rerun_py/tests/unit/test_geo_line_strings.py @@ -108,7 +108,7 @@ def test_geo_line_strings_single_line() -> None: # Regression test for #3643 # Single line string can be passed and is not interpreted as a batch of zero-sized line strings. reference = rr.GeoLineStrings(lat_lon=[rr.components.GeoLineString(lat_lon=[[0, 0], [1, 1]])]) - assert len(reference.line_strings) == 1 + assert reference.line_strings is not None and len(reference.line_strings) == 1 assert reference == rr.GeoLineStrings(lat_lon=rr.components.GeoLineString(lat_lon=[[0, 0], [1, 1]])) assert reference == rr.GeoLineStrings(lat_lon=[[[0, 0], [1, 1]]]) assert reference == rr.GeoLineStrings(lat_lon=[[0, 0], [1, 1]]) diff --git a/rerun_py/tests/unit/test_image_encoded.py b/rerun_py/tests/unit/test_image_encoded.py index d74212f46211..9da3cd1fb6a4 100644 --- a/rerun_py/tests/unit/test_image_encoded.py +++ b/rerun_py/tests/unit/test_image_encoded.py @@ -153,6 +153,7 @@ def bgr2nv12(bgr: cv2.typing.MatLike) -> cv2.typing.MatLike: assert len(warnings) == 1 assert type(img) is rr.Image + assert img.format is not None image_format_arrow = img.format.as_arrow_array()[0].as_py() diff --git a/rerun_py/tests/unit/test_instance_pose3d.py b/rerun_py/tests/unit/test_instance_pose3d.py index 8e2ed1c32ee6..0334c48b8653 100644 --- a/rerun_py/tests/unit/test_instance_pose3d.py +++ b/rerun_py/tests/unit/test_instance_pose3d.py @@ -77,8 +77,8 @@ def test_instance_poses3d() -> None: ) print(f"{arch}\n") - assert arch.translations == rr.components.PoseTranslation3DBatch._optional(translations) - assert arch.rotation_axis_angles == rr.components.PoseRotationAxisAngleBatch._optional(rotation_axis_angles) - assert arch.quaternions == rr.components.PoseRotationQuatBatch._optional(quaternions) - assert arch.scales == rr.components.PoseScale3DBatch._optional(scales) - assert arch.mat3x3 == rr.components.PoseTransformMat3x3Batch._optional(mat3x3) + assert arch.translations == rr.components.PoseTranslation3DBatch._converter(translations) + assert arch.rotation_axis_angles == rr.components.PoseRotationAxisAngleBatch._converter(rotation_axis_angles) + assert arch.quaternions == rr.components.PoseRotationQuatBatch._converter(quaternions) + assert arch.scales == rr.components.PoseScale3DBatch._converter(scales) + assert arch.mat3x3 == rr.components.PoseTransformMat3x3Batch._converter(mat3x3) diff --git a/rerun_py/tests/unit/test_line_strips2d.py b/rerun_py/tests/unit/test_line_strips2d.py index 6dab70773765..1747c0d35551 100644 --- a/rerun_py/tests/unit/test_line_strips2d.py +++ b/rerun_py/tests/unit/test_line_strips2d.py @@ -135,7 +135,7 @@ def test_single_line_strip2d() -> None: # Regression test for #3643 # Single linestrip can be passed and is not interpreted as batch of zero sized line strips. reference = rr.LineStrips2D([rr.components.LineStrip2D([[0, 0], [1, 1]])]) - assert len(reference.strips) == 1 + assert reference.strips is not None and len(reference.strips) == 1 assert reference == rr.LineStrips2D(rr.components.LineStrip2D([[0, 0], [1, 1]])) assert reference == rr.LineStrips2D([[[0, 0], [1, 1]]]) assert reference == rr.LineStrips2D([[0, 0], [1, 1]]) diff --git a/rerun_py/tests/unit/test_line_strips3d.py b/rerun_py/tests/unit/test_line_strips3d.py index 97d82cd6c8c5..8e7ab6bd510a 100644 --- a/rerun_py/tests/unit/test_line_strips3d.py +++ b/rerun_py/tests/unit/test_line_strips3d.py @@ -30,22 +30,24 @@ [], np.array([]), [ - [[0, 0, 2], [1, 0, 2], [1, 1, 2], (0, 1, 2)], # type: ignore[list-item] + [[0, 0, 2], [1, 0, 2], [1, 1, 2], (0, 1, 2)], # type: ignore[list-item] [[0, 0, 0], [0, 0, 1], [1, 0, 0], (1, 0, 1), - [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], # type: ignore[list-item] + [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], # type: ignore[list-item] ], [ - [Vec3D([0, 0, 2]), (1, 0, 2), [1, 1, 2], (0, 1, 2)], # type: ignore[list-item] + [Vec3D([0, 0, 2]), (1, 0, 2), [1, 1, 2], (0, 1, 2)], # type: ignore[list-item] [Vec3D([0, 0, 0]), (0, 0, 1), [1, 0, 0], (1, 0, 1), - [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], # type: ignore[list-item] + [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], # type: ignore[list-item] ], [ np.array([([0, 0, 2]), (1, 0, 2), [1, 1, 2], (0, 1, 2)], dtype=np.float32), - np.array([([0, 0, 0]), (0, 0, 1), [1, 0, 0], (1, 0, 1), [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], dtype=np.float32), # noqa + np.array([([0, 0, 0]), (0, 0, 1), [1, 0, 0], (1, 0, 1), [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], + dtype=np.float32), # noqa ], [ torch.tensor([([0, 0, 2]), (1, 0, 2), [1, 1, 2], (0, 1, 2)], dtype=torch.float32), - torch.tensor([([0, 0, 0]), (0, 0, 1), [1, 0, 0], (1, 0, 1), [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], dtype=torch.float32), # noqa + torch.tensor([([0, 0, 0]), (0, 0, 1), [1, 0, 0], (1, 0, 1), [1, 1, 0], (1, 1, 1), [0, 1, 0], (0, 1, 1)], + dtype=torch.float32), # noqa ], # NOTE: Not legal -- non-homogeneous. # np.array([ @@ -53,6 +55,8 @@ # [([0, 0, 0]), [0, 0, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1], [0, 1, 0], [0, 1, 1]], # ]), ] + + # fmt: on @@ -141,7 +145,7 @@ def test_single_line_strip2d() -> None: # Regression test for #3643 # Single linestrip can be passed and is not interpreted as batch of zero sized line strips. reference = rr.LineStrips3D([rr.components.LineStrip3D([[0, 0, 0], [1, 1, 1]])]) - assert len(reference.strips) == 1 + assert reference.strips is not None and len(reference.strips) == 1 assert reference == rr.LineStrips3D(rr.components.LineStrip3D([[0, 0, 0], [1, 1, 1]])) assert reference == rr.LineStrips3D([[[0, 0, 0], [1, 1, 1]]]) assert reference == rr.LineStrips3D([[0, 0, 0], [1, 1, 1]]) diff --git a/rerun_py/tests/unit/test_mesh3d.py b/rerun_py/tests/unit/test_mesh3d.py index 475b0739b193..9bcad5c0307d 100644 --- a/rerun_py/tests/unit/test_mesh3d.py +++ b/rerun_py/tests/unit/test_mesh3d.py @@ -39,7 +39,7 @@ def albedo_factor_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, Rgba32(0xAA0000CC)) - return AlbedoFactorBatch._optional(expected) + return AlbedoFactorBatch._converter(expected) def test_mesh3d() -> None: diff --git a/rerun_py/tests/unit/test_pinhole.py b/rerun_py/tests/unit/test_pinhole.py index 94a29ecdc074..cc85bb49d54d 100644 --- a/rerun_py/tests/unit/test_pinhole.py +++ b/rerun_py/tests/unit/test_pinhole.py @@ -37,9 +37,9 @@ def test_pinhole() -> None: arch = rr.Pinhole(image_from_camera=image_from_camera, resolution=resolution, camera_xyz=camera_xyz) print(f"{arch}\n") - assert arch.image_from_camera == PinholeProjectionBatch._optional([1, 2, 3, 4, 5, 6, 7, 8, 9]) - assert arch.resolution == ResolutionBatch._optional([1, 2] if resolution is not None else None) - assert arch.camera_xyz == ViewCoordinatesBatch._optional( + assert arch.image_from_camera == PinholeProjectionBatch._converter([1, 2, 3, 4, 5, 6, 7, 8, 9]) + assert arch.resolution == ResolutionBatch._converter([1, 2] if resolution is not None else None) + assert arch.camera_xyz == ViewCoordinatesBatch._converter( rr.components.ViewCoordinates.RDF if camera_xyz is not None else None ) diff --git a/rerun_py/tests/unit/test_plot_legend.py b/rerun_py/tests/unit/test_plot_legend.py index 13ea87868abb..3e0563068e1d 100644 --- a/rerun_py/tests/unit/test_plot_legend.py +++ b/rerun_py/tests/unit/test_plot_legend.py @@ -45,7 +45,7 @@ def test_scalar_axis() -> None: ) print(f"{arch}\n") - assert arch.corner == blueprint_components.Corner2DBatch._optional( + assert arch.corner == blueprint_components.Corner2DBatch._converter( none_empty_or_value(corner, rrb.Corner2D.LeftTop) ) - assert arch.visible == blueprint_components.VisibleBatch._optional(none_empty_or_value(visible, True)) + assert arch.visible == blueprint_components.VisibleBatch._converter(none_empty_or_value(visible, True)) diff --git a/rerun_py/tests/unit/test_scalar_axis.py b/rerun_py/tests/unit/test_scalar_axis.py index 7f14ba43d94e..a3ff7dad6f69 100644 --- a/rerun_py/tests/unit/test_scalar_axis.py +++ b/rerun_py/tests/unit/test_scalar_axis.py @@ -47,5 +47,5 @@ def test_scalar_axis() -> None: ) print(f"{arch}\n") - assert arch.range == rr.components.Range1DBatch._optional(none_empty_or_value(range, [42.1337, 1337.42])) - assert arch.zoom_lock == rrb.components.LockRangeDuringZoomBatch._optional(zoom_lock) + assert arch.range == rr.components.Range1DBatch._converter(none_empty_or_value(range, [42.1337, 1337.42])) + assert arch.zoom_lock == rrb.components.LockRangeDuringZoomBatch._converter(zoom_lock) diff --git a/rerun_py/tests/unit/test_series_styles.py b/rerun_py/tests/unit/test_series_styles.py index 99239587f291..0ed54b7394e2 100644 --- a/rerun_py/tests/unit/test_series_styles.py +++ b/rerun_py/tests/unit/test_series_styles.py @@ -28,11 +28,11 @@ def test_line_series() -> None: for input in inputs: if input.color is not None: - assert input.color == ColorBatch._optional([Color([255, 0, 0])]) + assert input.color == ColorBatch._converter([Color([255, 0, 0])]) if input.width is not None: - assert input.width == StrokeWidthBatch._optional([StrokeWidth(2.0)]) + assert input.width == StrokeWidthBatch._converter([StrokeWidth(2.0)]) if input.name is not None: - assert input.name == NameBatch._optional([Name("my plot")]) + assert input.name == NameBatch._converter([Name("my plot")]) def test_point_series() -> None: @@ -49,13 +49,13 @@ def test_point_series() -> None: for input in inputs: if input.color is not None: - assert input.color == ColorBatch._optional([Color([255, 0, 0])]) + assert input.color == ColorBatch._converter([Color([255, 0, 0])]) if input.marker_size is not None: - assert input.marker_size == MarkerSizeBatch._optional([MarkerSize(2.0)]) + assert input.marker_size == MarkerSizeBatch._converter([MarkerSize(2.0)]) if input.marker is not None: - assert input.marker == MarkerShapeBatch._optional([MarkerShape.Diamond]) + assert input.marker == MarkerShapeBatch._converter([MarkerShape.Diamond]) if input.name is not None: - assert input.name == NameBatch._optional([Name("my plot")]) + assert input.name == NameBatch._converter([Name("my plot")]) if __name__ == "__main__": diff --git a/rerun_py/tests/unit/test_tensor_slice_selection.py b/rerun_py/tests/unit/test_tensor_slice_selection.py index 3b0cff29f2e1..b18e06713547 100644 --- a/rerun_py/tests/unit/test_tensor_slice_selection.py +++ b/rerun_py/tests/unit/test_tensor_slice_selection.py @@ -71,15 +71,15 @@ def test_tensor_slice_selection() -> None: ) print(f"{arch}\n") - assert arch.width == rr.components.TensorWidthDimensionBatch._optional( + assert arch.width == rr.components.TensorWidthDimensionBatch._converter( none_empty_or_value(width, rr.components.TensorWidthDimension(dimension=2, invert=False)) ) - assert arch.height == rr.components.TensorHeightDimensionBatch._optional( + assert arch.height == rr.components.TensorHeightDimensionBatch._converter( none_empty_or_value(height, rr.components.TensorHeightDimension(dimension=3, invert=False)) ) - assert arch.indices == rr.components.TensorDimensionIndexSelectionBatch._optional( + assert arch.indices == rr.components.TensorDimensionIndexSelectionBatch._converter( none_empty_or_value(indices, indices_arrays[0]) ) - assert arch.slider == rrb.components.TensorDimensionIndexSliderBatch._optional( + assert arch.slider == rrb.components.TensorDimensionIndexSliderBatch._converter( none_empty_or_value(slider, [1, 2, 3]) ) diff --git a/rerun_py/tests/unit/test_transform3d.py b/rerun_py/tests/unit/test_transform3d.py index bebdf2e4ad34..4afa024102a3 100644 --- a/rerun_py/tests/unit/test_transform3d.py +++ b/rerun_py/tests/unit/test_transform3d.py @@ -125,25 +125,25 @@ def test_transform3d() -> None: ) print(f"{arch}\n") - assert arch.scale == rr.components.Scale3DBatch._required( + assert arch.scale == rr.components.Scale3DBatch( none_empty_or_value(scale, rr.components.Scale3D(scale)) # type: ignore[arg-type] ) - assert arch.rotation_axis_angle == rr.components.RotationAxisAngleBatch._required( + assert arch.rotation_axis_angle == rr.components.RotationAxisAngleBatch( none_empty_or_value(rotation_axis_angle, rr.components.RotationAxisAngle([1, 2, 3], Angle(deg=10))) ) - assert arch.quaternion == rr.components.RotationQuatBatch._required( + assert arch.quaternion == rr.components.RotationQuatBatch( none_empty_or_value(quaternion, rr.components.RotationQuat(xyzw=[1, 2, 3, 4])) ) - assert arch.translation == rr.components.Translation3DBatch._required( + assert arch.translation == rr.components.Translation3DBatch( none_empty_or_value(translation, rr.components.Translation3D([1, 2, 3])) ) - assert arch.mat3x3 == rr.components.TransformMat3x3Batch._required( + assert arch.mat3x3 == rr.components.TransformMat3x3Batch( none_empty_or_value(mat3x3, rr.components.TransformMat3x3([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) ) - assert arch.axis_length == rr.components.AxisLengthBatch._required( + assert arch.axis_length == rr.components.AxisLengthBatch( none_empty_or_value(axis_length, rr.components.AxisLength(1.0)) ) - assert arch.relation == rr.components.TransformRelationBatch._required(relation) + assert arch.relation == rr.components.TransformRelationBatch(relation) def test_transform_mat3x3_snippets() -> None: diff --git a/rerun_py/tests/unit/test_uuid.py b/rerun_py/tests/unit/test_uuid.py index 61166704b1b2..f4a9fc98a9a8 100644 --- a/rerun_py/tests/unit/test_uuid.py +++ b/rerun_py/tests/unit/test_uuid.py @@ -11,7 +11,7 @@ def uuids_expected(obj: Any) -> Any: expected = none_empty_or_value(obj, uuids_arrays[-1]) - return UuidBatch._optional(expected) + return UuidBatch._converter(expected) def test_uuid() -> None: diff --git a/rerun_py/tests/unit/test_view_blueprint.py b/rerun_py/tests/unit/test_view_blueprint.py index ae517f6b3240..cd97eb2bcfa1 100644 --- a/rerun_py/tests/unit/test_view_blueprint.py +++ b/rerun_py/tests/unit/test_view_blueprint.py @@ -55,6 +55,6 @@ def test_view_blueprint() -> None: # Equality checks on some of these are a bit silly, but at least they test out that the serialization code runs without problems. assert arch.class_identifier == ViewClassBatch("3D") - assert arch.display_name == NameBatch._optional(none_empty_or_value(display_name, "3D view")) - assert arch.space_origin == ViewOriginBatch._optional(none_empty_or_value(space_origin, "/robot/arm")) - assert arch.visible == VisibleBatch._optional(none_empty_or_value(visible, False)) + assert arch.display_name == NameBatch._converter(none_empty_or_value(display_name, "3D view")) + assert arch.space_origin == ViewOriginBatch._converter(none_empty_or_value(space_origin, "/robot/arm")) + assert arch.visible == VisibleBatch._converter(none_empty_or_value(visible, False)) diff --git a/rerun_py/tests/unit/test_view_coordinates.py b/rerun_py/tests/unit/test_view_coordinates.py index d8788276c4a3..86d71a95fc13 100644 --- a/rerun_py/tests/unit/test_view_coordinates.py +++ b/rerun_py/tests/unit/test_view_coordinates.py @@ -17,8 +17,7 @@ def view_coordinates_expected(obj: Any) -> rrc.ViewCoordinatesBatch: return rrc.ViewCoordinatesBatch(expected) -VIEW_COORDINATES_INPUTS: list[ViewCoordinatesArrayLike | None] = [ - None, +VIEW_COORDINATES_INPUTS: list[ViewCoordinatesArrayLike] = [ rrc.ViewCoordinates([ rrc.ViewCoordinates.ViewDir.Right, rrc.ViewCoordinates.ViewDir.Down, diff --git a/rerun_py/tests/unit/test_viewport_blueprint.py b/rerun_py/tests/unit/test_viewport_blueprint.py index bd05fdfac912..84d0fe4b4d14 100644 --- a/rerun_py/tests/unit/test_viewport_blueprint.py +++ b/rerun_py/tests/unit/test_viewport_blueprint.py @@ -76,10 +76,10 @@ def test_viewport_blueprint() -> None: ) print(f"{arch}\n") - assert arch.root_container == RootContainerBatch._optional(none_empty_or_value(root_container, uuid_bytes0)) - assert arch.maximized == ViewMaximizedBatch._optional(none_empty_or_value(maximized, uuid_bytes1)) - assert arch.auto_layout == AutoLayoutBatch._optional(none_empty_or_value(auto_layout, True)) - assert arch.auto_views == AutoViewsBatch._optional(none_empty_or_value(auto_views, False)) - assert arch.past_viewer_recommendations == ViewerRecommendationHashBatch._optional( + assert arch.root_container == RootContainerBatch._converter(none_empty_or_value(root_container, uuid_bytes0)) + assert arch.maximized == ViewMaximizedBatch._converter(none_empty_or_value(maximized, uuid_bytes1)) + assert arch.auto_layout == AutoLayoutBatch._converter(none_empty_or_value(auto_layout, True)) + assert arch.auto_views == AutoViewsBatch._converter(none_empty_or_value(auto_views, False)) + assert arch.past_viewer_recommendations == ViewerRecommendationHashBatch._converter( none_empty_or_value(past_viewer_recommendations, [123, 321]) )